Как указать инъекции сеттера для статического класса, используя StructureMap? - PullRequest
3 голосов
/ 27 декабря 2011

В настоящее время я работаю над этим фрагментом кода из книги шаблонов проектирования:

public static class DomainEvents
{
    public static IDomainEventHandlerFactory DomainEventHandlerFactory { get; set; }

    public static void Raise<T>(T domainEvent) where T : IDomainEvent
    {
        DomainEventHandlerFactory.GetDomainEventHandlersFor(domainEvent).ForEach(h => h.Handle(domainEvent));
    }
}

Это связано с подключением DomainEvents, и этот конкретный фрагмент кода отвечает за то, что я могу вызвать событие с помощью *Метод 1004 * в DomainEvents.

Вот код в моем файле Bootstrapper:

public class ControllerRegistry : Registry
{
        public ControllerRegistry()
        {
            ForRequestedType<IDomainEventHandlerFactory>().TheDefault.Is.OfConcreteType<StructureMapDomainEventHandlerFactory>();
            ForRequestedType<IDomainEventHandler<OrderSubmittedEvent>>().AddConcreteType<OrderSubmittedHandler>();
        }
    }

Когда я иду к доступу DomainEvents.Raise со своего уровня Service (в этом примере яповышение OrderSumittedEvent), DomainEvents равно null (когда это должно быть установлено через StructureMap):

public class OrderService
{
    public void Create(Order order)
    {
        DomainEvents.Raise(new OrderSubmittedEvent() { Order = order });
    }
}

Если я не установлю вручную DomainEvents.DomainEventHandlerFactory на StructureMapDomainEventHandlerFactory, вот так:

public class OrderService
{
    public void Create(Order order)
    {
        // this is the manual assignment I have to make into the DomainEventHandlerFactory of
        // the static DomainEvents class. Basically, this is what StructureMap should take care
        // of for me, but is not.
        DomainEvents.DomainEventHandlerFactory = new StructureMapDomainEventHandlerFactory();

        DomainEvents.Raise(new OrderSubmittedEvent() { Order = order });
    }
}

Ниже представлен вывод StrucutureMap с использованием .WhatDoIHave(), и похоже, что StructureMap имеет настроенный экземпляр StructureMapDomainEventHandlerFactory для типа IDomainEventHandlerFactory.Вот дамп:

================================================================================================================================================================================================================================================================================================================================================================================================
PluginType                                                                                  Name                                                                                                                          Description                                                                                                                                                           
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Func`1<TResult> (Func`1<TResult>)                                                                                                                                                                                                                                                                                                                                                               
Scoped as:  Transient

                                                                                        311731d7-60c7-46de-9ef4-24608f21df04                                                                                                                                                                                                                                                                
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IDomainEventHandlerFactory (DE.Infrastructure.Domain.Events.IDomainEventHandlerFactory)     dbcb010c-fa92-4137-85b8-161ab17c2c98                                                                                          Configured Instance of DE.Infrastructure.Domain.Events.StructureMapDomainEventHandlerFactory, DE.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Scoped as:  Transient

                                                                                            dbcb010c-fa92-4137-85b8-161ab17c2c98                                                                                          Configured Instance of DE.Infrastructure.Domain.Events.StructureMapDomainEventHandlerFactory, DE.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IDomainEventHandler`1<OrderSubmittedEvent> (IDomainEventHandler`1<OrderSubmittedEvent>)     DE.Services.DomainEventHandlers.OrderSubmittedHandler, DE.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null     Configured Instance of DE.Services.DomainEventHandlers.OrderSubmittedHandler, DE.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                      
Scoped as:  Transient

                                                                                            DE.Services.DomainEventHandlers.OrderSubmittedHandler, DE.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null     Configured Instance of DE.Services.DomainEventHandlers.OrderSubmittedHandler, DE.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                      
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IContainer (StructureMap.IContainer)                                                        e24f9e45-caaf-48b6-89f7-d8125310102a                                                                                          Object:  StructureMap.Container                                                                                                                                       
Scoped as:  Transient

                                                                                            e24f9e45-caaf-48b6-89f7-d8125310102a                                                                                          Object:  StructureMap.Container                                                                                                                                       
================================================================================================================================================================================================================================================================================================================================================================================================

Я использовал StructureMap, но я не использовал Setter Injection, и мне не приходилось сталкиваться с использованием StructureMap со статическими классами (если это даже имеет смысл), поэтомуЯ немного растерялся из-за того, почему этот код не работает.

Возможно ли использовать Setter Injection со статической реализацией такого класса?Я правильно не использую StructureMap?Должен ли StructureMap отвечать за создание класса DomainEvents как Singleton, и я могу избавиться от статической реализации?

Спасибо, Майк

1 Ответ

0 голосов
/ 29 ноября 2014

Можно ли использовать Setter Injection со статической реализацией такого класса?

Нет. Это возможно только для создаваемых классов.

Правильно ли я не использую StructureMap?

Вы не. Внедрение зависимостей имеет дело с созданием и предоставлением экземпляров . По определению статические классы не могут быть созданы в коде и поэтому не могут быть введены.

Должен ли StructureMap отвечать за создание класса DomainEvents как Singleton, и я могу избавиться от статической реализации?

Похоже, что основной особенностью этого проекта является использование одного экземпляра, поэтому событие вызывается только один раз. Я не уверен, какой шаблон проектирования вы используете, но во многих случаях вы можете заменить Action<T> или Func<T> событиями, и если вы используете правильный образ жизни синглтона, вы, вероятно, можете зарегистрировать один экземпляр, который может быть разделен между всеми ваших классов, а не прибегать к статическим классам.

Если статическое событие абсолютно необходимо, вы можете внедрить экземпляр IDomainEventHandlerFactory в код запуска вашего приложения, разрешив экземпляр и установив его вручную после завершения кода регистрации (в вашем корне композиции ) .

// Provide the DI container with configuration
var container = DIConfig();

// Set the static event
DomainEvents.DomainEventHandlerFactory = container.Resolve<IDomainEventHandlerFactory>();

Чтобы ваше приложение не злоупотребляло сеттером, вызывая его более одного раза или используя его до того, как оно установлено, вы можете добавить несколько защитных предложений в ваш статический класс.

public static class DomainEvents
{
    private static IDomainEventHandlerFactory domainEventHandlerFactory;

    public static IDomainEventHandlerFactory DomainEventHandlerFactory 
    { 
        get
        {
            return domainEventHandlerFactory;
        }
        set
        {
            if (value == null)
                throw new ArgumentNullException("value");
            if (domainEventHandlerFactory != null)
                throw new ArgumentException("DomainEventHandlerFactory is already set and cannot be set again.");
            domainEventHandlerFactory = value;
        }
    }

    public static void Raise<T>(T domainEvent) where T : IDomainEvent
    {
        ThrowIfNotInitialized()
        DomainEventHandlerFactory.GetDomainEventHandlersFor(domainEvent).ForEach(h => h.Handle(domainEvent));
    }

    private static void ThrowIfNotInitialized()
    {
        if (domainEventHandlerFactory == null)
        {
            throw new MvcSiteMapException("Not initialized. You must set DomainEventHandlerFactory at application start.");
        }
    }
}
...