Simple Injector:使用构造函数参数注册开放泛型类型

时间:2017-04-19 13:43:47

标签: c# dependency-injection inversion-of-control ioc-container simple-injector

我创建了一个通用类型

public interface IContext<T> {}

并且,我实现了一个类型(带有参数的构造函数)

public class Context<T> : IContext<T> { public Context(string url, string key) { } ... }

我想注册简单的注射器。使用下面的代码,我不知道如何传递构造函数的值

container.Register(typeof(IContext<>), typeof(Context<>))

This如果我在构造函数参数中传递了一个类型,则会显示一种方法。但是,对我来说只是原始类型。通过重写构造解决方案行为,我可能会实现这一目标。但是,我真的不知道如何利用它。有人可以指导我找到合适的方式来注册吗?

1 个答案:

答案 0 :(得分:1)

当将原始依赖关系处理为开放式通用注册时,典型的解决方案是将配置值集合提取到DTO中,并将该DTO注入到类型的构造函数中;这允许您将新配置对象注册为容器:

我创建了一个通用类型

public interface IContext {}

并且,我实现了一个类型(带有参数的构造函数)

public class ContextConfiguration
{
    public readonly string Url;
    public readonly string Key;
    public ContextConfiguration(string url, string key) { ... }
}

public class Context<T> : IContext<T>
{
    public Context(ContextConfiguration config)
    {
    }
    ...
}

// Configuration
container.RegisterSingleton(new ContextConfiguration(...));
container.Register(typeof(IContext<>), typeof(Context<>));

如果您无法更改该类型的构造函数,则可以创建放置在Composition Root内的该类型的子类。此子类型再次使用此配置DTO:

// Part of the Composition Root
private class ContextConfiguration
{
    public readonly string Url;
    public readonly string Key;
    public ContextConfiguration(string url, string key) { ... }
}

private class CompositionRootContext<T> : Context<T>
{
    public Context(ContextConfiguration config) : base(config.Url, config.Key)
    {
    }
    ...
}

// Configuration
container.RegisterSingleton(new ContextConfiguration(...));
container.Register(typeof(IContext<>), typeof(CompositionRootContext<>));

如果密封Context<T>,您可以覆盖parameter injection behavior,但通常情况下,您正在处理由外部库定义的类型。对于外部类型,通常最好将它们隐藏在应用程序定制的抽象之后(根据DIP)。您可以让应用程序依赖于应用程序定义的接口,而不是让应用程序代码依赖于IContext<T>。作为Composition Root的一部分,您将实现Adapter,使特定于应用程序的界面适应Context<T>。该适配器的构造函数将能够使用此配置DTO。