如何注册手动创建的装饰器实例

How to register manually-created decorator instance

通常,要使用构造函数注入注册一些配置值,我会这样做:

string setting = ConfigurationManager.AppSettings["SomeSetting"];
container.Register<IService>(new Service(setting));

你如何完成类似的事情,以便将配置值传递给装饰器构造函数?

是创建一些可以注入装饰器的配置提供程序 class 的唯一方法吗?似乎 RegisterDecorator 应该有一个重载,允许根据需要手动更新 class。

有几种方法可以实现这一点。如果对象图的那部分很简单,手动构建对象图可能会得到最好的结果:

container.RegisterSingleton<IService>(new ServiceDecorator(
    setting,
    new RealService()));

// or 
container.Register<IService>(() => new ServiceDecorator(
    setting,
    new RealService()));

在 Simple Injector 中没有 RegisterDecorator 的委托重载,这意味着您不能使用手动连接的 RegisterDecorator 注册装饰器,但是有一些替代方法。

您可以将设置值提取到它自己的 class。这允许将抽象注入到装饰器中:

container.RegisterSingleton<MySetting>(new MySetting(setting));
container.RegisterDecorator(typeof(IService), typeof(ServiceDecorator));

public ServiceDecorator : IService {
    public ServiceDecorator(MySetting setting, IService decoratee) { }
}

或者您可以将设置注入装饰器的 属性:

container.RegisterDecorator(typeof(IService), typeof(ServiceDecorator));
container.RegisterInitializer<ServiceDecorator>(dec => dec.Setting = setting);

public ServiceDecorator : IService {
    public string Setting { get; set; }
    public ServiceDecorator(IService decoratee) { }
}

或者您可以将 Setting 设为静态 属性:

ServiceDecorator.Setting = setting;
container.RegisterDecorator(typeof(IService), typeof(ServiceDecorator));

如果装饰器本身无法更改,您可以从中派生 class:

public ServiceDecoratorWithSetting : ServiceDecorator {
    public static string Setting { get; set; }
    public ServiceDecorator(IService decoratee) : base(Setting, decoratee) { }
}

ServiceDecoratorWithSetting.Setting = setting;
container.RegisterDecorator(typeof(IService), typeof(ServiceDecoratorWithSetting));

最后一个选项是 override parameter injection behavior,但这有点复杂,我通常只在集成场景中建议这样做。