2010-10-31 104 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); 
    } 
} 

現在我註冊庫如下:StructureMap - 如何註冊和解析的開放式泛型類型

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>(); 

這實在是很麻煩,尤其是如果有新一起來到倉庫。

一種更簡單,更好的登記是:

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

但是,這是行不通的。 StructureMap每次都說我沒有爲PluginFamily Core.Domain.Bases.Repositories.ITeamEmployeeRepository定義默認實例。

我搜索了計算器,發現一些新的東西:

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

但還是同樣的錯誤消息。

如何使用StructureMap 2.6.1.0註冊我的存儲庫?

+0

雖然這不直接回答你的問題,請看看這篇文章:http://stackoverflow.com/questions/4128640/how-to-remove-unit-of-work-functionality-from-repositories-using -ioc/41 32186#4132186。它顯示了實現存儲庫模式的另一種方式。這個實現將你的倉庫隱藏在一個工作單元的後面,你只需要註冊一個'IUnitOfWorkFactory'就完成了。 – Steven 2010-11-11 08:52:05

回答

7

我找到了解決方案。

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

WithDefaultConventions是顯示代碼的重要組成部分,因爲在這種設置你說StructureMap使用mappping ITeamEmployeeRepository到TeamEmployeeRepository的約定。所以StructureMap從這樣一種假設着手,即類別被命名爲接口的名稱,而不需要前綴I

-1

我最近通過做一個小的重新設計來解決了類似的問題,這使得一切都變得簡單了。這也可能對你有用。您可以嘗試從設計中刪除特定的接口,例如ITeamEmployeeRepositoryILoanedItemRepository。我這樣做的方式是使用擴展方法。這裏有一個例子:

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 
} 

之後,我創建了一個IRepositoryFactory,讓我創造了一定類型的存儲庫:

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

到位有這個接口時,很容易創建的實現這個工廠要求容器創建一個具體的Repository<T>。該RepositoryFactory看起來是這樣的:

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

有了這個設計,你只需要通過其IRepositoryFactory接口登記的具體RepositoryFactory和你做。而不是在舊設計中注入IRepository<ITeamEmployeeRepository>,現在注入IRepositoryFactory並讓客戶調用CreateNewRepository<T>方法。由於使用擴展方法,您可以在存儲庫上調用類型特定的方法。

這樣做的另一個優點是您無需重新實施您在每個實現上最初在ITeamEmployeeRepository上定義的方法。

這種設計在我的情況下效果很好,特別是因爲我的IRepository<T>接口使用表達式樹。當然,我不可能看到這樣的設計是否適合你,但我希望它能。

祝你好運。

+0

「這樣做的另一個優點是,您無需重新實施您在每個實施上最初在ITeamEmployeeRepository上定義的方法。」情況並非如此,因爲存儲庫已經在實施標準的CRUD內容。具體的ITeamEmployeeRepository只有特定的要求。 – Rookian 2010-10-31 13:48:54

+0

也許我誤解了,但我想到你會使用ITeamEmployeeRepository來實現團隊員工特定的方法。這些方法在「存儲庫」類中沒有意義。我想你在這個接口上有特定於實體的方法,因爲沒有方法的接口不會很有用。諸如'GetByYear'或CRUD操作在Repository 上沒有意義。您通常至少會有兩個此ITeamEmployeeRepository接口的實現... – Steven 2010-10-31 15:04:37

+0

一個在您的生產環境中,另一個在您的單元測試環境中。這意味着在這種情況下,您必須在生產'TeamEmployeeRepository'和使用的測試庫中實現'GetByYear'。通過擴展方法,您不僅可以避免多次寫入,而且還可以覆蓋該代碼。但是,也許我誤解了你的需求。 – Steven 2010-10-31 15:05:15

-2

您將需要創建自己的ITypeScanner並在您的Scan()呼叫中註冊。以GenericConnectionScanner的源代碼作爲起點。您將不用搜索類型來查看它們是否實現IRepository<T>,而是查看它們是否實現了實現IRepository<T>的任何接口,然後註冊該接口的類型。

更新:IRepository<T>的所有談話讓我過度思考這一點,當它真的是一個不相關的細節。按照Rookian的建議使用DefaultConventions掃描器。

2

我發現這個問題谷歌搜索「結構圖解決通用」。現有的答案很好但很複雜。對於那些尋求簡單的答案:對接口ISome和實現類的一些我們寫

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

雖然通用ISome <牛逼>和實現類的一些<牛逼>我們寫

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

而這一切

相關問題