如何使用Unity解决静态类中的依赖关系?

Dav*_*Dev 16 c# extension-methods unity-container

我有以下扩展方法,它(自然地)存在于静态类中.

public static class MyExtensions
{
    [Dependency]
    private static IMyDataContext _myDataContext { get; set; }

    public static void MyExtensionMethod(this MyType myType)
    {
        // do stuff

        _myDataContext.DoAwesomeThing();
    }
}
Run Code Online (Sandbox Code Playgroud)

_myDataContext对象为null.

通常我会使用UnityContainer注册类型,但由于这是一个静态类,我不能.

我需要实例化_ myDataContext以便在需要时它不为空?

Joh*_*ger 20

正如您已经提到的,Unity不能用于解析类,因为它是静态的.有几种选择.我个人最喜欢的是使用抽象工厂模式.我倾向于调整模式只是为了与DI一起工作.

工厂通常看起来像这样:

/// <summary>
/// Creates an IMyDataContext instance
/// </summary>
public static class MyDataContextFactory
{
    /// <summary>
    /// The factory used to create an instance
    /// </summary>
    static Func<IMyDataContext> factory;

    /// <summary>
    /// Initializes the specified creation factory.
    /// </summary>
    /// <param name="creationFactory">The creation factory.</param>
    public static void SetFactory(Func<IMyDataContext> creationFactory)
    {
        factory = creationFactory;
    }

    /// <summary>
    /// Creates a new IMyDataContext instance.
    /// </summary>
    /// <returns>Returns an instance of an IMyDataContext </returns>
    public static IMyDataContext CreateContext()
    {
        if (factory == null) throw new InvalidOperationException("You can not create a context without first building the factory.");

        return factory();
    }
}
Run Code Online (Sandbox Code Playgroud)

在引导过程中(无论您何时设置服务注册),都可以初始化工厂以解决依赖关系.

MyDataContextFactory.SetFactory(() => this.Container.Resolve<IMyDataContext>());
Run Code Online (Sandbox Code Playgroud)

现在,在您的扩展方法中,您将获取上下文.

public static class MyExtensions
{
    public static void MyExtensionMethod(this MyType myType)
    {
        MyDataContextFactory.CreateContext().DoAwesomeThing();
    }
}
Run Code Online (Sandbox Code Playgroud)

您的Unity上下文注册,如果有条件解决它,可以处理服务的各种不同配置.如果可以通过Unity之外的其他设置来设置上下文,则该所有者可以直接传入扩展方法将使用的新委托.

我倾向于避免将容器本身传递到我的工厂,因为这开始将容器紧密耦合到我的应用程序.如果我要把任何东西都送到工厂,我宁愿它是一个工厂代表用来通过DI解决,而不是通过DI容器本身.