Как разрешить зависимость в статическом классе с Unity?

У меня есть следующий метод расширения, который существует (естественно) в статическом классе.

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

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

        _myDataContext.DoAwesomeThing();
    }
}

_myDataContext объект является нулевым.

Обычно я бы использовал UnityContainer зарегистрировать тип, но так как это статический класс, я не могу.

Что мне нужно для создания _myDataContext чтобы не было нуля когда мне это нужно?

1 ответ

Решение

Как вы уже упоминали, Unity нельзя использовать для разрешения класса, поскольку он статический. Есть несколько вариантов для этого. Мой личный фаворит - использование шаблона Abstract Factory. Я склонен подстраивать паттерн, чтобы работать с 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();
    }
}

В процессе начальной загрузки (где бы вы ни настраивали свои регистрации служб), вы можете инициализировать фабрику для разрешения зависимости.

MyDataContextFactory.SetFactory(() => this.Container.Resolve<IMyDataContext>());

Теперь в вашем методе расширения вы получаете контекст.

public static class MyExtensions
{
    public static void MyExtensionMethod(this MyType myType)
    {
        MyDataContextFactory.CreateContext().DoAwesomeThing();
    }
}

Ваша Unity регистрация контекста может обрабатывать различные конфигурации сервиса, если есть условия для его разрешения. Если существует вероятность того, что контекст может быть установлен чем-то другим, кроме Unity, этот владелец может просто передать новый делегат, который будет использовать метод расширения.

Я стараюсь избегать передачи самих контейнеров на свои фабрики, так как это приводит к тому, что контейнеры начинают плотно соединяться с моим приложением. Если я собираюсь передать что-либо на фабрику, я бы предпочел, чтобы это был делегат фабрики, используемый для разрешения через DI, а не для передачи самого контейнера DI.

Другие вопросы по тегам