具有开放通用接口的 Windsor 类型工厂

Ric*_*ard 2 dependency-injection castle-windsor factory-pattern

在我的应用程序中,我想依赖一个类中的多个存储库,每次都不需要所有存储库。我没有在不必要的情况下为每个实例构建一个实例,而是使用了Windsor 中的Typed Factory 工具

然而,为每个存储库注册一个工厂有点烦人,我想用一个开放的通用注册来代替它。我想要做的是如下所示:

container.Register(
    Component.For<IFactory<IRepository<>>>().AsFactory()
);
Run Code Online (Sandbox Code Playgroud)

但是,这是一个语法错误,因为缺少 IRepository 的类型参数。有没有我可以使用的语法来完成这项工作?

注意:我知道我可以注册一个无类型的 Factory 接口并使用它来创建多个组件。我对这样做不感兴趣,因为这基本上依赖于服务定位器 - 如果我没有注册依赖项,那么在代码尝试使用它之前我不会知道它 - 用我知道的方法即使我还没有创建实例,在构造函数中也有 this。

完整(简化)示例如下:

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

Phi*_*rdt 5

您的工厂界面定义有点过于“开放”。更改您的工厂界面如下:

public interface IRepositoryFactory<T>
{
    IRepository<T> Create();
    void Release(IRepository<T> instance);
}
Run Code Online (Sandbox Code Playgroud)

然后你可以注册:

container.Register(Component.For(typeof(IRepositoryFactory<>)).AsFactory());
Run Code Online (Sandbox Code Playgroud)

并解决:

var factoryA = container.Resolve<IRepositoryFactory<TestA>>();
var factoryB = container.Resolve<IRepositoryFactory<TestB>>();
Run Code Online (Sandbox Code Playgroud)