我正在尝试自动注册存储库:
这有效,但我不喜欢它,因为在服务层类中,我必须向构造函数提供具体的EntityRepository<T>
,而不是提供接口IRepository<T>
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(typeof(BaseObjectContext),
new PerExecutionContextLifetimeManager());
var serviceType = typeof(IRepository<>)
.MakeGenericType(repository.DomainType);
var implementationType = typeof(EntityRepository<>)
.MakeGenericType(repository.ObjectContextType);
container.RegisterType(serviceType, implementationType,
new TransientLifetimeManager());
};
return container;
}
我想使用container.RegisterType<TFrom, TTo>(new TransientLifetimeManager());
自动注册我的存储库
我知道问题出在哪里,因为这种注册方式要求您提供接口和类的真实名称,例如IRepository<Customer>
和EntityRepository<Customer>
。我可以这样做,但我必须逐个列出存储库,如果您正在处理100个Domain对象的项目,我认为这是不可行的。
我想像这样自动执行它们,这样我就可以在服务层类中注入IRepository<T>
。
// 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;
}
答案 0 :(得分:1)
我不确定你要解决的问题是什么,但我认为你的设计从长远来看不会起作用。然而,我清楚的是,你有一个很大的域,并希望能够在服务类中注入IRepository<T>
个实例,但希望利用实体框架代码生成器的批量注册,以防止你从必须维护大量代码,这是一个令人钦佩的目标。
但是,您尝试将IRepository<T>
实例注入服务。虽然存储库是一种常见的设计模式,但直接将存储库注入服务对我来说从来没有用过,在实体框架的上下文中看起来很奇怪,它使用工作单元模式(ObjectContext
)来集中应用程序和服务器之间的操作。数据库。注入存储库意味着每个存储库下必须存放ObjectContext
,并且您可能希望在单个服务中注入的所有存储库实例中具有相同的ObjectContext
,因为您的操作可能应该是原子的。 / p>
IMO最好不要将IRepository<T>
个实例注入您的服务,而是注入UnitOfWork
甚至更好:IUnitOfWorkFactory
。 IUnitOfWorkFactory
可以创建一个新的UnitOfWork
实例(服务必须在完成后进行处置),UnitOfWork
将包含IRepository<T>
实例的列表,并包含SubmitChanges
{1}}方法。
通过在IRepository<T> GetRepository<T>()
上实施UnitOfWork
方法,您可以有效地获取特定的存储库,而无需进行任何批量注册,以便连接100个存储库。这可以在IUnitOfWork
实现中为您完成。
从应用程序的角度来看,如果UnitOfWork
包含特定IRepository<T>
实现的属性(例如public IRepository<Customer> Customers { get; set; }
)会更好,但这确实意味着您需要添加新属性当新实体被添加到系统时,这可能不是你喜欢的。但是,根据我的经验,这并不会对可维护性造成太大影响,同时它极大地提高了代码的可读性。
这个设计可能看起来有点牵强,但我实际上有一个类似的设计在生产中运行超过半年,它完美地工作。我在博客上写了这篇文章(见Faking your LINQ provider),其他人已经在他们的应用程序中成功采用了这种方法。它似乎也适用于其他人。也许这对你很有意思,或者它至少可以给你一些如何有效地做到这一点的想法。我使用依赖注入,并且在给定的设计中,我只需配置几种类型即可使其运行。
我希望这会有所帮助。