2012-12-19 14 views
7

Zacznę od tego, nie jestem pewien, czy jest to możliwe. Uczę się generycznych i mam kilka repozytoriów w mojej aplikacji. Próbuję utworzyć interfejs, który ma typowy typ i przekształca go w coś, z czego wszystkie repozytoria mogą dziedziczyć. Przejdźmy teraz do mojego pytania.Próba użycia generycznego z Entity Framework

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

Czy można użyć nazwy rodzajowej, aby określić, co znaleźć?

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. 
} 

Aby wyjaśnić nieco lepiej, zastanawiałem się nad ciągiem, int lub dowolnym typem, który chciałem wyszukać. Co mam nadzieję na to, co mogę powiedzieć x.something gdzie coś jest równa zmiennej przekazanej w.

mogę ustawić dowolny repozytorium do mojego dbcontext używając

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

jakieś sugestie?

Odpowiedz

4

Jeśli używasz Expression<Func<T, bool>> zamiast A tak:

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

ty może zapytać o typ za pomocą linq i podać zapytanie w kodzie wywołującym klasę repozytorium.

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

i nazwać tak:

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

A biorąc pod uwagę, że jest to ogólny wyraz, nie trzeba zaimplementować go w każdym repozytorium, można mieć to w ogólnym repozytorium bazowej.

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

Osobiście podoba mi się to podejście, ale wielu nie. Oznacza to, że użytkownik repozytorium musi wiedzieć, jakie wyrażenia są bezpieczne, a które nie, jako że jest to nieszczelna abstrakcja. – stevenrcfox

0

Używam kombinacji klas interfejsu i abstrakcji, aby osiągnąć dokładnie to.

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 

następnie klasy pochodzące Czy mają kilka konkretnych metod obiektu lub wręcz nic i po prostu pracować

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