Как вы уже упоминали, 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();
}
}
В вашем процессе начальной загрузки (где когда-либо вам настроить ваши регистрации службы), вы можете инициализировать фабрику, чтобы устранить зависимость.
MyDataContextFactory.SetFactory(() => this.Container.Resolve<IMyDataContext>());
Теперь в вашем методе расширения вы выбираете контекст.
public static class MyExtensions
{
public static void MyExtensionMethod(this MyType myType)
{
MyDataContextFactory.CreateContext().DoAwesomeThing();
}
}
Ваша регистрация Единства контекста может обрабатывать различные различные конфигурации службы, если есть условия для ее решения. Если существует вероятность того, что контекст может быть установлен чем-то другим, кроме Unity, этот владелец может просто передать новый делегат, который будет использовать метод расширения.
Я стараюсь не пропускать контейнеры непосредственно на свои фабрики, так как это начинает сжимать жесткие соединения контейнеров с моим приложением. Если я собираюсь передать что-либо на фабрику, я бы предпочел, чтобы это был делегат фабрики, используемый для разрешения через DI, чем сам контейнер DI.
Как я могу выполнить описанную выше реализацию? Как я хочу передать любой интерфейс? IMyDataContext может быть любым интерфейсом. Можете ли вы представить какую-либо реализацию? –
Вы бы просто создали методы «SetContext» и «CreateContext». Ваша реализация разрешит '' вместо 'IDataContext'. Вам нужно было бы сохранить 'Func ' вместо этого, а затем попытаться передать его 'Func ' при вызове 'CreateContext'. Честно говоря, хотя я бы оценил использование метода расширения, который должен возвращать данные из статического класса, подобного этому. DI зависимостей в свой конструктор вызывающих, затем укажите зависимость в вызове метода расширения как параметр метода. –