Pergunta

Eu suponho que este é mais um discurso público, mas por que não posso get c # para inferir o meu tipo de Id?

public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>

e um EntityObject definido com um GUID como um ID do seguinte modo:

public Foo : EntityObject<Guid>

herança da classe EntityObject abstrato definidos da seguinte forma:

public abstract class EntityObject<IdT>
{
    public IdT id { get; set; }
}

O uso do método get seria o seguinte:

IRepository repository = new Repository();
var hydratedFoo = repository.Get<Foo>(someGuidId);

editado para prestar esclarecimentos adicionais.

Foi útil?

Solução

É difícil dizer, uma vez que você dada apenas duas declarações, e não como você está usando-los. IDT é um outro tipo de parâmetro em algum lugar? (Se fosse TId, que sugerem que é - mas o fato de que você está usando EntityT para um outro parâmetro de tipo, ao contrário convenções, sugere que talvez IdT é tão bem ...)

Agora, assumindo IdT é realmente Guid no seu caso, como deve ser o compilador trabalho que você Foo média? Poderia haver outros tipos decorrentes EntityObject<Guid>.

Em suma, você não nos deu informações suficientes para dizer nada com certeza, mas parece que você está fazendo basicamente exigências descabidas sobre o compilador.

EDIT: Ok, aqui está o meu palpite sobre o que você tem, utilizando convenções de nomenclatura normais:

public interface IRepository
{
    TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>
}

public abstract class EntityObject<TId>
{
    public IdT id { get; set; }
}

public class Foo : EntityObject<Guid> {} 

Você quer fazer:

IRepository repository = GetRepositoryFromSomewhere();
Foo foo = repository.Get<Foo>(someGuid);

Considerando que atualmente você tem que fazer:

Foo foo = repository.Get<Foo, Guid>(someGuid);

Sim, o compilador está tornando-se muito ligeiramente mais difícil para você do que o necessário. Um todo 6 caracteres extras, por uma questão de manter a linguagem mais simples e as regras de inferência de tipos mais fáceis de entender.

digite Basicamente inferência é uma questão de tudo ou nada - ou todas parâmetros de tipo são inferidos ou nenhum deles é. Isso mantém simples que você não precisa trabalhar fora que estão sendo especificados e quais não são. Isso é parte do problema, e a outra parte é que você só pode expressar restrições sobre os parâmetros de tipo de método - você não pode ter:

class Repository<TEntity>
{
    TEntity Get<TId>(TId id) where TEntity : EntityObject<TId>
}

Porque isso é constrangedor TEntity, não TId. Novamente, esse tipo de coisa faz a inferência de tipos mais simples.

Agora você poderia potencialmente escrever:

Foo foo = repository.Get(someGuid).For<Foo>();

com um método Get apropriado e uma interface extra. Eu acho que eu, pessoalmente, prefiro Get<Foo, Guid> uso apenas embora.

Outras dicas

Uma declaração como

public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>

exige que IDT é um tipo concreto. Se você quiser parametrizar IDT, bem como, você precisa usar

public EntityT Get<EntityT, IdT>(IdT id) where EntityT : EntityObject<IdT>

Mas isso não é provavelmente o que você gostaria.

É por isso que eu tenho todos, mas desistiu de tipos principais genéricos com entidades genéricas. Eu não conseguia descobrir como obter meus entidades de ter principais tipos genéricos sem aspersão os dois em todo o lugar. Agora eu tenha resolvido em chaves inteiras (que é o que eu tenho em todos os lugares de qualquer maneira), mas ele se sente mal.

Se o seu método de assinatura ficou assim:

public TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>

O compilador teria algo para trabalhar com ...

Você, então, chamar começar com algo como:

EDIT (eu estava errado): Produtos p = Get (id);

Product p = Get<Product, Guid>(id);

O Jon pregado essa resposta com o seu lugar lá em cima, então eu vou calar a boca e rastejar de volta no meu buraco.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top