Pergunta

Eu tenho uma classe definida da seguinte forma;

public abstract class Repository<TEntity, TDataContext> : DisposableBaseClass
   where TEntity : class
   where TDataContext : DataContext, new()
{...contains Linq to SQL related functionality

Em concreto sub-classe I definir os tipos como tal;

public class ConcreteRepo : Repository<LSTableClass, LSDataContext>

No próximo nível, eu tenho objetos de negócios que mantêm o objeto Repository como uma variável privada.

Este foi excelentes;

private ConcreteRepo _repository;

No entanto, eu então reformulado isso em uma classe pai para todos os objetos de negócios -. Esta classe pai mantém o padrão Dispose repositório / utensílios de dispor de repositório etc

O meu problema é que eu simplesmente não consegue obter o direito sintaxe para a declaração da variável.

O mais próximo que eu vim é;

protected Repository<Object, DataContext> _repository;

mas isso dá o erro de compilação:

"Erro 1 'System.Data.Linq.DataContext' deve ser um tipo não-abstrato com um construtor sem parâmetros pública, a fim de usá-lo como parâmetro 'TDataContext' no tipo genérico ou método' ... .Repository' ... "

Eu tentei várias outras coisas mas bateu outros problemas.

No objeto camada de negócios herdar essa classe abstrata eu estou criando e usando a variável _repository com um elenco;

(Repository<LSTableClass, LSDataContext>)_repository = new ConcreteRepo();
  • e eu acho que isso vai ficar bem, supondo que eu posso obter este direito declaração no pai.

Se eu não posso chegar a este trabalho eu tenho que declarar a _repository em cada objeto de negócios, com os detalhes completos / concreto tipo, e implementar o padrão Dispose em cada um para esclarecer. Não é o fim do mundo, mas eu gostaria de não ter de.

Foi útil?

Solução

Se eu entender o seu problema corretamente, você precisa adicionar um terceiro parâmetro genérico, o tipo de repositório, que é obrigado a ser um descendente de Repository com os tipos de argumento apropriado.

Para delinear um pouco mais:

public abstract class Repository<TEntity,TDataContext>
    where TEntity : class
    where TDataContext : DataContext, new() {}

public abstract class BusinessObject<TEntity,TDataContext,TRepository>
    where TEntity : class
    where TDataContext : DataContext, new()
    where TRepository : Repository<TEntity,TDataContext>
{
    TRepository _repository;
}

public class ConcreteObject : BusinessObject<LSTableClass,LSDataContext,ConcreteRepo>
{ // ...

Eu sei que provavelmente não é tão compacto quanto você gostaria, mas o que é necessário para reduzir esse baixo ainda efetivamente ainda mantêm a tipagem forte, é de ordem superior tipos genéricos (classes chamado tipo em Haskell): uma forma de indicar que parâmetros de tipo são eles próprios genérico, e pode levar parâmetros de tipo.

Outras dicas

A sua declaração

protected Repository<Object, DataContext> _repository;

não funcionou por causa da restrição que você colocou sobre ele:

...    
where TDataContext : DataContext, new()

Especificamente a parte new().

Eu estou supondo que você quer 'injetar' um objeto satisfazer a sua interface genérica.

Duas coisas:

  • Você não pode converter entre Repository<Object, DataContext> e Repository<LSTableClass, LSDataContext>. Não com C # 3. Isso é chamado Contravariance / Covariance e não estará disponível até C # 4. Em C # 3 estes são dois tipos completamente diferentes.

  • Se você quiser armazenar um dentro membro do genérico de uma classe, em seguida, os argumentos de tipo ou tem que ser tipos de concreto, ou eles devem ser declarados como parâmetros de tipo na declaração da classe pai (fazendo que genérico).

Opções:

  • Usar argumentos de tipo genérico em sua classe pai.
  • Remova a nova restrição () de sua declaração de classe.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top