C# Unity容器注册表类型<;t从,到>;问题

C# Unity容器注册表类型<;t从,到>;问题,c#,.net,dependency-injection,unity-container,ioc-container,C#,.net,Dependency Injection,Unity Container,Ioc Container,我正在尝试自动注册存储库: 这是可行的,但我不喜欢,因为在服务层类中,我必须向构造函数提供具体的EntityRepository,而不是提供接口IRepository 公共静态IContainer注册表( 此IContainer容器,参数程序集[]程序集) { 变量存储库=( 从程序集中的程序集 来自程序集中的类型。GetTypes() 其中typeof(ObjectContext).IsAssignableFrom(type) 来自type.GetProperties()中的属性 让prope

我正在尝试自动注册存储库:

这是可行的,但我不喜欢,因为在服务层类中,我必须向构造函数提供具体的
EntityRepository
,而不是提供接口
IRepository

公共静态IContainer注册表(
此IContainer容器,参数程序集[]程序集)
{
变量存储库=(
从程序集中的程序集
来自程序集中的类型。GetTypes()
其中typeof(ObjectContext).IsAssignableFrom(type)
来自type.GetProperties()中的属性
让propertyType=property.propertyType
其中propertyType.IsGenericType
where propertyType
.GetGenericTypeDefinition()==typeof(对象集)
选择新的
{
ObjectContextType=类型,
DomainType=propertyType.GetGenericArguments()[0]
})
.ToList();
foreach(存储库中的var存储库)
{
container.RegisterType(typeof(BaseObjectContext),
新的PerExecutionContextLifetimeManager());
var serviceType=typeof(IRepository)
.MakeGenericType(repository.DomainType);
var implementationType=typeof(EntityRepository)
.MakeGenericType(repository.ObjectContextType);
container.RegisterType(serviceType、implementationType、,
新的TransientLifetimeManager());
};
返回容器;
}
我想使用
container.RegisterType(new TransientLifetimeManager())自动注册我的存储库
我知道问题出在哪里,因为这种注册方式要求您提供接口和类的真实名称,例如
IRepository
EntityRepository
。我可以这样做,但我必须一个接一个地列出存储库,如果您处理的是一个包含100个域对象的项目,我认为这是不可行的。 我希望像这样自动执行这些操作,这样我就可以在服务层类中插入
IRepository

// Configure root container.Register types and life time 
// managers for unity builder process
public static IContainer RegisterRepositories(
    this IContainer container, params Assembly[] assemblies)
{
    var repositories = (
        from assembly in assemblies
        from type in assembly.GetTypes() 
        where typeof(ObjectContext).IsAssignableFrom(type)
        from property in type.GetProperties()
        let propertyType = property.PropertyType
        where propertyType.IsGenericType 
        where propertyType
            .GetGenericTypeDefinition() == typeof(ObjectSet<>)
        select new 
        {
            ObjectContextType = type, 
            DomainType = propertyType.GetGenericArguments()[0] 
        })
        .ToList()

    foreach (var repository in repositories)
    {
        container.RegisterType<BaseObjectContext>(
            new PerExecutionContextLifetimeManager(), 
            new InjectionConstructor());

        container.RegisterType<IRepository<repository.DomainType>,
             EntityRepository<repository.ObjectContextType>>(
            new TransientLifetimeManager());
    };

    return container;
}
//配置根容器。注册类型和生存时间
//unity builder流程管理器
公共静态IContainer注册表存储(
此IContainer容器,参数程序集[]程序集)
{
变量存储库=(
从程序集中的程序集
来自程序集中的类型。GetTypes()
其中typeof(ObjectContext).IsAssignableFrom(type)
来自type.GetProperties()中的属性
让propertyType=property.propertyType
其中propertyType.IsGenericType
where propertyType
.GetGenericTypeDefinition()==typeof(对象集)
选择新的
{
ObjectContextType=类型,
DomainType=propertyType.GetGenericArguments()[0]
})
托利斯先生()
foreach(存储库中的var存储库)
{
container.RegisterType(
新建PerExecutionContextLifetimeManager(),
新的InjectionConstructor());
container.RegisterType(
新的TransientLifetimeManager());
};
返回容器;
}

我不确定您试图解决的问题是什么,但我认为您的设计从长远来看是行不通的。然而,我很清楚的是,您拥有一个很大的域,并且希望能够在服务类中注入
IRepository
实例,但希望利用批注册和实体框架代码生成器,以避免您不得不维护大量代码,这是一个令人钦佩的目标

但是,您尝试将
IRepository
实例注入到服务中。尽管存储库是一种常见的设计模式,但将存储库直接注入服务对我来说从来都不起作用,而且在实体框架的上下文中似乎很奇怪,实体框架使用工作单元模式(
ObjectContext
)来集中应用程序和数据库之间的操作。注入存储库,意味着在每个存储库下必须放置一个
ObjectContext
,并且您可能希望在注入单个服务的所有存储库实例中具有相同的
ObjectContext
,因为您的操作可能是原子的

在我看来,最好不要将
IRepository
实例注入到您的服务中,而是注入一个
UnitOfWork
,甚至更好:一个
IUnitOfWorkFactory
IUnitOfWorkFactory
可以创建一个新的
UnitOfWork
实例(服务完成后必须处理该实例),而
UnitOfWork
将保存一个
IRepository
实例列表,并包含一个
SubmitChanges
方法

通过在
UnitOfWork
上实现
IRepository GetRepository()
方法,您可以有效地获得特定的存储库,而无需进行任何批量注册,甚至可以连接100个存储库。这可以在
IUnitOfWork
实现中为您完成

从应用程序的角度来看,如果
UnitOfWork
包含特定
IRepository
实现的属性,例如
publiciRepository客户{get;set;}
,那就更好了,但这确实意味着您需要在向系统添加新实体时添加新属性,这可能不是你喜欢的东西。然而,根据我的经验,这并不会对可维护性造成太大的伤害,同时也大大提高了代码的可读性

这个设计对你来说可能有点牵强,但实际上我有一个类似的设计已经在生产中运行了半年多了,它工作得非常完美。我已经在博客上对此进行了讨论(请参阅),其他人已经在他们的应用程序中成功地采用了这种方法。它似乎也适用于其他人。也许这对你来说很有趣,或者它至少可以给你一些如何提高效率的想法
// Configure root container.Register types and life time 
// managers for unity builder process
public static IContainer RegisterRepositories(
    this IContainer container, params Assembly[] assemblies)
{
    var repositories = (
        from assembly in assemblies
        from type in assembly.GetTypes() 
        where typeof(ObjectContext).IsAssignableFrom(type)
        from property in type.GetProperties()
        let propertyType = property.PropertyType
        where propertyType.IsGenericType 
        where propertyType
            .GetGenericTypeDefinition() == typeof(ObjectSet<>)
        select new 
        {
            ObjectContextType = type, 
            DomainType = propertyType.GetGenericArguments()[0] 
        })
        .ToList()

    foreach (var repository in repositories)
    {
        container.RegisterType<BaseObjectContext>(
            new PerExecutionContextLifetimeManager(), 
            new InjectionConstructor());

        container.RegisterType<IRepository<repository.DomainType>,
             EntityRepository<repository.ObjectContextType>>(
            new TransientLifetimeManager());
    };

    return container;
}