2010-10-31 13 views
6
public interface IRepository<T> where T : Entity 
{ 
    void Delete(T entity); 
    T[] GetAll(); 
    T GetById(int id); 
    void SaveOrUpdate(T enity); 
    void Merge(T entity); 
} 

public interface ITeamEmployeeRepository : IRepository<TeamEmployee> 
{ 
    PagedList<TeamEmployee> GetPagedTeamEmployees(int pageIndex, int pageSize); 
} 


public class Repository<T> : IRepository<T> where T : Entity 
{ 
    private readonly ISession _session; 

    protected Repository() 
    { 
     _session = GetSession(); 
    } 

    public virtual void Delete(T entity) 
    { 
     _session.Delete(entity); 
    } 

    public virtual T[] GetAll() 
    { 
     return _session.CreateCriteria<T>().List<T>().ToArray(); 
    } 

    public virtual T GetById(int id) 
    { 
     return _session.Get<T>(id); 
    } 

    public virtual void SaveOrUpdate(T enity) 
    { 
     _session.SaveOrUpdate(enity); 
    } 

    public void Merge(T entity) 
    { 
     _session.Merge(entity); 
    } 

    protected ISession GetSession() 
    { 
     return new SessionBuilder().GetSession(); 
    } 
} 

public class TeamEmployeeRepository : Repository<TeamEmployee>, ITeamEmployeeRepository 
{ 
    public PagedList<TeamEmployee> GetPagedTeamEmployees(int pageIndex, int pageSize) 
    { 
     return GetSession().QueryOver<TeamEmployee>() 
      .Fetch(x => x.Employee).Eager 
      .Fetch(x => x.Team).Eager 
      .ToPagedList(pageIndex, pageSize); 
    } 
} 

Na razie zarejestrowania repozytorium następująco:StructureMap - Jak zarejestrować się i rozwiązać otwartą ogólny typ

For<ILoanedItemRepository>().Use<LoanedItemRepository>(); 
For<ITeamEmployeeRepository>().Use<TeamEmployeeRepository>(); 
For<IArticleRepository>().Use<ArticleRepository>(); 
For<ISalesmanRepository>().Use<SalesmanRepository>(); 
For<ISalesmanArticleRepository>().Use<SalesmanArticleRepository>(); 
For<IGoodsGroupRepository>().Use<GoodsGroupRepository>(); 
For<IEmployeeRepository>().Use<EmployeeRepository>(); 

Jest to bardzo kłopotliwe, zwłaszcza jeśli chodzi wzdłuż nowych repozytoriów.

Łatwiej i lepiej byłoby Rejestracja:

For(typeof(IRepository<>)).Use(typeof(Repository<>)); 

Ale to nie działa. StructureMap za każdym razem mówi mi, że nie zdefiniowano domyślnej instancji dla PluginFamily Core.Domain.Bases.Repositories.ITeamEmployeeRepository.

Szukałem na stackoverflow i znaleźć coś nowego:

Scan(x => 
{ 
    x.AssemblyContainingType(typeof(TeamEmployeeRepository)); 
    x.AddAllTypesOf(typeof (IRepository<>)); 
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>)); 
}); 

ale nadal ten sam komunikat o błędzie.

Jak mogę zarejestrować swoje repozytoria za pomocą StructureMap 2.6.1.0?

+0

Chociaż to nie odpowiada bezpośrednio na twoje pytanie, proszę spojrzeć na ten artykuł: http://stackoverflow.com/questions/4128640/how-to-remove-unit-of-work-functionality-from-repositoriesi-using -ioc/41 32186 # 4132186. Pokazuje alternatywny sposób implementacji wzorca repozytorium. Implementacja ukrywa twoje repozytorium za jednostką pracy i musisz tylko zarejestrować jedną 'IUnitOfWorkFactory' i gotowe. – Steven

Odpowiedz

7

Znalazłem rozwiązanie.

Scan(x => 
{ 
    x.WithDefaultConventions(); 
    x.AssemblyContainingType(typeof(TeamEmployeeRepository)); 
    x.AddAllTypesOf(typeof(Repository<>)); 
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>)); 
}); 

WithDefaultConventions jest ważnym elementem przedstawionym kodzie, bo z tego ustawienia można powiedzieć StructureMap używać Konwencji mappping ITeamEmployeeRepository do TeamEmployeeRepository. Tak więc StructureMap wychodzi z założenia, że ​​klasa nazywa się jak nazwa interfejsu bez prefiksu I.

-1

Ostatnio rozwiązałem coś podobnego, wykonując małe przeprojektowanie, które znacznie uprościło wszystko. To może również zadziałać dla ciebie. Możesz spróbować usunąć ze swojego projektu określone interfejsy, takie jak ITeamEmployeeRepository i ILoanedItemRepository. Sposób, w jaki to zrobiłem, był przez użycie metod rozszerzenia. Oto przykład:

public static class RepositoryExtensions 
{ 
    public static TeamEmployee GetById(
     this IRepository<TeamEmployee> repository, int id) 
    { 
     return repository.Single(e => e.TeamEmployeeId == id); 
    } 

    public static IQueryable<Salesman> GetActiveSalesmen(
     this IRepository<ISalesmanRepository> repository) 
    { 
     return repository.Where(salesman => salesman.Active); 
    } 

    // etc 
} 

Potem stworzył IRepositoryFactory który pozwalał mi tworzyć repozytoria pewnego typu:

public interface IRepositoryFactory 
{ 
    IRepository<T> CreateNewRepository<T>(); 
} 

Kiedy mając tego interfejsu w miejscu łatwo jest stworzyć implementację tej fabryki, która prosi kontener o stworzenie betonu Repository<T>. RepositoryFactory mógłby wyglądać następująco:

public class RepositoryFactory : IRepositoryFactory 
{ 
    public IRepository<T> CreateNewRepository<T>() 
    { 
     return ObjectFactory.GetInstance(typeof(Repository<T>)); 
    } 
} 

Dzięki tej konstrukcji trzeba tylko zarejestrować konkretną RepositoryFactory przez interfejs IRepositoryFactory i gotowe. Zamiast wstrzykiwania IRepository<ITeamEmployeeRepository> w starym projekcie, należy teraz wstrzyknąć IRepositoryFactory i pozwolić klientowi na wywołanie metody CreateNewRepository<T>. Z powodu użycia metod rozszerzeń można wywoływać specyficzne dla danego typu metody w repozytorium.

Kolejną zaletą jest to, że nie trzeba ponownie wdrażać metod, które początkowo zdefiniowano na ITeamEmployeeRepository przy każdej implementacji.

Ten projekt sprawdził się bardzo dobrze w mojej sytuacji, zwłaszcza że moje interfejsy IRepository<T> wykorzystują drzewa ekspresji. Oczywiście nie jest możliwe sprawdzenie, czy taki projekt działa dla ciebie, ale mam nadzieję, że tak się stanie.

Powodzenia.

+0

"Inną zaletą tego jest to, że nie trzeba ponownie wdrażać metod, które początkowo zdefiniowałeś na ITeamEmployeeRepository w każdej implementacji." Tak nie jest, ponieważ Repozytorium implementuje już standardowe produkty CRUD. Określony element ITeamEmployeeRepository ma tylko określone wymagania. – Rookian

+0

Być może źle rozumiem, ale wyobrażałem sobie, że używałbyś 'ITeamEmployeeRepository' dla specyficznych metod dla pracowników zespołu. Te metody nie miałyby żadnego znaczenia w klasie 'Repository '. Przypuszczam, że masz na tym interfejsie metody specyficzne dla jednostki, ponieważ interfejs bez metod nie byłby bardzo użyteczny. Rzeczy takie jak operacje 'GetByYear' lub CRUD, które nie mają żadnego znaczenia w Repozytorium . Normalnie będziesz mieć co najmniej dwie implementacje interfejsu 'ITeamEmployeeRepository' ... – Steven

+0

Jedna w twoim środowisku produkcyjnym i jedna dla twojego środowiska testowego. Oznacza to, że w takich sytuacjach musiałbyś zaimplementować 'GetByYear' zarówno w swojej produkcji' TeamEmployeeRepository' i przy użyciu repozytorium testów. Dzięki metodzie rozszerzenia nie tylko oszczędzasz sobie konieczności wielokrotnego pisania, ale także pozwala ci to zakryć. Ale znowu, być może źle rozumiem twoje potrzeby. – Steven

-2

Musisz utworzyć własną ITypeScanner i zarejestrować ją w swoim telefonie Scan(). Popatrz na kod źródłowy GenericConnectionScanner jako punkt wyjścia. Zamiast przeszukiwać typy, aby zobaczyć, czy implementują one IRepository<T>, będziesz sprawdzał, czy implementują dowolny interfejs implementujący IRepository<T>, a następnie rejestrują typ tego interfejsu.

AKTUALIZACJA: Cała rozmowa z IRepository<T> kazała mi przesadzić z tym, kiedy to naprawdę nieistotne szczegóły. Wystarczy użyć skanera DefaultConventions, zgodnie z sugestią Rookian.

2

Znalazłem to pytanie googling "structuremap resolve generic". Istniejące odpowiedzi są dobre, ale złożone. Dla osób poszukujących prostą odpowiedź: dla interfejsu ISome i klasy wykonawczego Niektóre piszemy

c.For<ISome>().Use<Some>() 

Choć dla rodzajowego ISome <T> i wykonawczego klasy Niektóre <T> piszemy

c.For(typeof(ISome<>)).Use(typeof(Some<>)) 

i to wszystko

Powiązane problemy