2015-05-22 2 views
9

У меня есть следующий метод расширения, который существует (естественно) в статическом классе.Как разрешить зависимость в статическом классе с 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, чтобы он не был нулевым, когда он мне нужен?

ответ

12

Как вы уже упоминали, 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.

+0

Как я могу выполнить описанную выше реализацию? Как я хочу передать любой интерфейс? IMyDataContext может быть любым интерфейсом. Можете ли вы представить какую-либо реализацию? –

+0

Вы бы просто создали методы «SetContext» и «CreateContext». Ваша реализация разрешит '' вместо 'IDataContext'. Вам нужно было бы сохранить 'Func ' вместо этого, а затем попытаться передать его 'Func ' при вызове 'CreateContext'. Честно говоря, хотя я бы оценил использование метода расширения, который должен возвращать данные из статического класса, подобного этому. DI зависимостей в свой конструктор вызывающих, затем укажите зависимость в вызове метода расширения как параметр метода. –

Смежные вопросы