Как разрешить зависимость в статическом классе с 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.