c# - 使用 UsingFactoryMethod 在 Windsor 中进行通用注册

标签 c# generics dependency-injection inversion-of-control castle-windsor

我们目前的代码看起来像下面这样,一个工厂被注入(inject)到很多类中,然后调用工厂来获取他们想要的实例。

public class Service
{
     public Service(IFactory factory)
     {
          _car = factory.GetCar<Entity>();
     }
}

public class Car : ICar
{
}

public interface IFactory
{
    ICar<TEntity> GetCar<TEntity>();

    IBoat<TEntity> GetBoat<TEntity>();
}

public class Factory : IFactory
{
    ConnectionDetails _connectionDetails;    

    public Factory(ConnectionDetails connectionDetails)
    {
        _connectionDetails = connectionDetails;
    }

    TEntity GetCar<TEntity>()
    {
        var car = new Car<TEntity>(_connectionDetails);
        car.Initialize();
        return car;
    }
}

我希望能够创建一个解决方案,允许直接在 Car<TEntity> 上请求依赖项无需先经过工厂。

下面是为单个 TEntity 安装的示例,但我如何将其设置为通用的?

我试过使用开放泛型,但我看不出如何从 .UsingFactoryMethod() 中获得正确的返回类型.

我知道我可以得到 RequestedType来自 CreationContext ,但我不知道如何使用它来解决这个问题。

public class Installer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
                    Component.For<ICar<TEntity>>().UsingFactoryMethod(
                        kernel =>
                        {
                            var factory = kernel.Resolve<IFactory>();
                            return factory.GetCar<TEntity>();
                        }));
    }
}

最佳答案

就我个人而言,我发现混合依赖注入(inject)的工厂可能有点反模式,因为它隐藏了对象图根以外的其他地方的实现/创建细节。此外,当将两者混合时,最终谁负责创建和维护对象及其生命周期变得不清楚。

我建议您转向允许容器根据通用基础接口(interface)/类完全处理创建细节。

void Main()
{
    var container = new WindsorContainer();
    container.Install(new Installer());

    var car = container.Resolve<Car>();
    car.Dump();
}

public class Service
{
    private ICar<CarEntity> _car;

    public Service(ICar<CarEntity> car)
    {
        _car = car;
    }
}

public class TEntity { }
public class CarEntity : TEntity { }
public class BoatEntity : TEntity { }

public interface ICreatable { }
public interface ICar<TEntity> : ICreatable { }

public class Car : ICar<TEntity> 
{
    private ConnectionDetails _connectionDetails;

    public Car(ConnectionDetails connectionDetails)
    {
        _connectionDetails = connectionDetails; 
        Initialize();
    }

    public void Initialize() {}
}

public class ConnectionDetails { }

public class Installer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<ConnectionDetails>()
                     .ImplementedBy<ConnectionDetails>());

        container.Register(
            Classes.FromAssemblyInThisApplication()
                .BasedOn(typeof(ICreatable))
                .WithServiceAllInterfaces()
                .WithServiceSelf()
                .LifestyleTransient());
    }
}

关于c# - 使用 UsingFactoryMethod 在 Windsor 中进行通用注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36851282/

相关文章:

generics - 扩展 Scala 集合

c# - 避免将具体的数据库上下文类注入(inject) Controller

c# - 更改所有 Windows Forms 窗体上的设置

c# - 使用 webClient 保存网络驱动器照片

c# - 在日期时间选择器 C# 中停用特定日期

c# - Double.NaN 的变量赋值变为 Double.NegativeInfinity

.net - 如果 T 是类型 arg,如何使用 Nullable<T>?

java - 类泛型的类型不匹配

java - 如何在 Jersey 2.0 中使用 HK2 依赖注入(inject)?

dependency-injection - 在进行构造函数或 setter 注入(inject)时,依赖项的正确粒度是多少?