StructureMap - 如何注册和解析开放泛型类型

Roo*_*ian 8 c# structuremap repository ioc-container

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我按如下方式注册存储库:

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>();
Run Code Online (Sandbox Code Playgroud)

这真的很麻烦,特别是如果有新的存储库.

更容易和更好的注册将是:

For(typeof(IRepository<>)).Use(typeof(Repository<>));
Run Code Online (Sandbox Code Playgroud)

但这不起作用.StructureMap每次都说我没有为PluginFamily Core.Domain.Bases.Repositories.ITeamEmployeeRepository定义默认实例.

我在stackoverflow上搜索并找到了新的东西:

Scan(x =>
{
    x.AssemblyContainingType(typeof(TeamEmployeeRepository));
    x.AddAllTypesOf(typeof (IRepository<>));
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
});
Run Code Online (Sandbox Code Playgroud)

但仍然是相同的错误消息.

如何在StructureMap 2.6.1.0中注册我的存储库?

Roo*_*ian 9

我找到了解决方案.

Scan(x =>
{
    x.WithDefaultConventions();
    x.AssemblyContainingType(typeof(TeamEmployeeRepository));
    x.AddAllTypesOf(typeof(Repository<>));
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
});
Run Code Online (Sandbox Code Playgroud)

WithDefaultConventions是显示代码的重要部分,因为使用此设置,您可以说StructureMap使用将ITeamEmployeeRepository映射到TeamEmployeeRepository的约定.因此,StructureMap假设该类被命名为没有前缀I的接口名称.


Rus*_*tam 5

我在谷歌搜索“结构图解析通用”时发现了这个问题。现有的答案很好但很复杂。对于那些寻求简单答案的人:对于接口 ISome 和实现类 Some 我们写

c.For<ISome>().Use<Some>()
Run Code Online (Sandbox Code Playgroud)

而对于泛型 ISome<T> 和实现类 Some<T> 我们写

c.For(typeof(ISome<>)).Use(typeof(Some<>))
Run Code Online (Sandbox Code Playgroud)

就这样