2012-12-19 12 views
7

Vorrei iniziare, non sono sicuro che sia possibile. Sto imparando i farmaci generici e ho diversi repository nella mia app. Sto cercando di creare un'interfaccia che accetta un tipo generico e lo converte in qualcosa che tutti i repository possono ereditare da. Ora alla mia domanda.Tentativo di utilizzare un generico con Entity Framework

public interface IRepository<T> 
{ 
    IEnumerable<T> FindAll(); 
    IEnumerable<T> FindById(int id); 
    IEnumerable<T> FindBy<A>(A type); 
} 

È possibile utilizzare un generico per determinare cosa trovare da?

public IEnumerable<SomeClass> FindBy<A>(A type) 
{ 
    return _context.Set<SomeClass>().Where(x => x. == type); // I was hoping to do x.type and it would use the same variable to search. 
} 

Per chiarire un po 'meglio stavo considerando di essere una stringa, INT o qualsiasi tipo ho voluto cercare. Quello che sto sperando per è quello che posso dire x.something dove la cosa è uguale alla variabile passata in.

posso impostare qualsiasi repository alla mia DbContext utilizzando i

public IDbSet<TEntity> Set<TEntity>() where TEntity : class 
{ 
    return base.Set<TEntity>(); 
} 

qualche suggerimento?

risposta

4

Se si utilizza Expression<Func<T, bool>> invece di A come questo:

public interface IRepository<T> 
{ 
    ... // other methods 
    IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate); 
} 

È può interrogare il tipo usando linq e specificare la query nel codice che chiama la classe repository.

public IEnumerable<SomeClass> FindBy(Expression<Func<SomeClass, bool>> predicate) 
{ 
    return _context.Set<SomeClass>().Where(predicate); 
} 

E chiamare in questo modo:

var results = repository.FindBy(x => x.Name == "Foo"); 

E dato che si tratta di un'espressione generica, non è necessario per la sua attuazione in ogni repository, si può avere nel repository di base generico.

public IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate) 
{ 
    return _context.Set<T>().Where(predicate); 
} 
+2

Personalmente mi piace questo approccio, ma molti non lo fanno. Ciò significa che l'utente del repository deve sapere quali sono le espressioni EF sicure e quali no, in quanto tale è un'astrazione che perde. – stevenrcfox

0

Uso una combinazione di classi Interface e Abstract per ottenere esattamente questo.

public class RepositoryEntityBase<T> : IRepositoryEntityBase<T>, IRepositoryEF<T> where T : BaseObject 
// 
public RepositoryEntityBase(DbContext context) 
    { 
     Context = context; 
//etc 

public interface IRepositoryEntityBase<T> : IRepositoryEvent where T : BaseObject //must be a model class we are exposing in a repository object 

{ 
    OperationStatus Add(T entity); 
    OperationStatus Remove(T entity); 
    OperationStatus Change(T entity); 
    //etc 

poi le classi derivate può un avere un paio di metodi specifici oggetti o addirittura nulla e solo di lavoro

public class RepositoryModule : RepositoryEntityBase<Module>, IRepositoryModule{ 
    public RepositoryModule(DbContext context) : base(context, currentState) {} 
} 
//etc