在我的应用程序中,我想依赖于类中的多个存储库,而不是每次都需要所有这些存储库。我不是在不必要的地方构建每个实例,而是使用Windsor中的Typed Factory facility。
但是,为每个存储库注册工厂有点令人厌烦,我想用开放的通用注册替换它。我想做的事情如下:
container.Register(
Component.For<IFactory<IRepository<>>>().AsFactory()
);
但是,由于缺少IRepository的类型参数,这是一个语法错误。我可以使用哪种语法来实现这个功能吗?
注意:我知道我可以注册一个无类型的Factory接口,并使用它来创建多个组件。我对此不感兴趣,因为这实际上是依赖于服务定位器 - 如果我没有注册依赖项,那么在代码尝试使用它之前我不会知道它 - 我知道的方法这在构造函数中,即使我还没有创建实例。
下面的完整(简化)示例:
public class TestA { }
public class TestB { }
public interface IRepository<T> { T Create(); }
public class Repository<T> : IRepository<T>
{
public T Create() { return Activator.CreateInstance<T>(); }
}
public interface IFactory<T>
{
T Create();
void Release(T instance);
}
class Program
{
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
// Individual registrations of repositories here are fine
Component.For<IRepository<TestA>>().ImplementedBy<Repository<TestA>>(),
Component.For<IRepository<TestB>>().ImplementedBy<Repository<TestB>>()
);
container.Register(
// Individual registrations of factories - works, but trying to avoid!
Component.For<IFactory<IRepository<TestA>>>().AsFactory(),
Component.For<IFactory<IRepository<TestB>>>().AsFactory()
);
container.Register(
// Generic Registration of Factories - syntax errors
// Component.For<IFactory<IRepository<>>>().AsFactory()
// Component.For(typeof(IFactory<IRepository<>>)).AsFactory()
);
var factoryA = container.Resolve<IFactory<IRepository<TestA>>>();
var factoryB = container.Resolve<IFactory<IRepository<TestB>>>();
var repoA = factoryA.Create();
var repoB = factoryB.Create();
Console.WriteLine("Everything worked");
}
}
答案 0 :(得分:4)
您的工厂界面定义有点过于“开放”。按如下方式更改工厂界面:
public interface IRepositoryFactory<T>
{
IRepository<T> Create();
void Release(IRepository<T> instance);
}
然后你可以注册:
container.Register(Component.For(typeof(IRepositoryFactory<>)).AsFactory());
并解决:
var factoryA = container.Resolve<IRepositoryFactory<TestA>>();
var factoryB = container.Resolve<IRepositoryFactory<TestB>>();
答案 1 :(得分:1)
有一种模式可以将存储库组合在一起。它被称为unit of work。因此,不是创建用于创建存储库的工厂,而是创建引用这些存储库的工作单元。例如:
public abstract class UnitOfWork : IDisposable
{
// here is your factory
protected abstract IRepository<T> GetRepository<T>();
public IRepository<User> Users
{
get { return this.GetRepository<User>();
}
public IRepository<Customer> Customers
{
get { return this.GetRepository<Customer>();
}
// etc..
}
在您的Composition Root中,您可以定义一个UnitOfWork
实现,其中包含对Windsor的引用,并使您能够获得IRepository<T>
实现:
internal sealed class WindsorUnitOfWork : UnitOfWork
{
private WindsorContainer container;
public WindsorUnitOfWork(WindsorContainer container)
{
this.container = container;
}
protected override IRepository<T> GetRepository<T>()
{
return this.container.Resolve<IRepository<T>>();
}
}
并注册如下:
container.Register(Component.For<UnitOfWork>()
.ImplementedBy<WindsorUnitOfWork>()
.LifeStyle.Transient);
消费者现在可以非常方便地使用存储库:
private readonly UnitOfWork db;
public KarmaService(UnitOfWork db)
{
this.db = db;
}
public int CalculateKarmaForActiveUsersByName(string name)
{
var users =
from user in this.db.Users
where user.Name == name
where user.Active
select user;
return users.Sum(user => user.Karma);
}