如何使用 StructureMap 为静态类指定 setter 注入?
我目前正在研究设计模式书中的这段代码片段:
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,这个特定的代码段负责允许我通过 DomainEvents 上的 Raise 方法引发事件。
以下是我的 Bootstrapper 文件中的代码:
public class ControllerRegistry : Registry
{
public ControllerRegistry()
{
ForRequestedType<IDomainEventHandlerFactory>().TheDefault.Is.OfConcreteType<StructureMapDomainEventHandlerFactory>();
ForRequestedType<IDomainEventHandler<OrderSubmittedEvent>>().AddConcreteType<OrderSubmittedHandler>();
}
}
当我从服务层访问 DomainEvents.Raise
时(在本示例中,我将引发 OrderSumissEvent
),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 });
}
}
下面是使用 .WhatDoIHave()
的 StructureMap 的输出,并且看起来 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 注入,也不必处理将 StructureMap 与静态类一起使用(如果这有意义的话),所以我有点不明白为什么这段代码不起作用。
是否可以将 Setter 注入与这样的类的静态实现一起使用? 我没有正确使用 StructureMap 吗? StructureMap 是否应该负责将 DomainEvents 类创建为单例,并且我可以摆脱静态实现?
谢谢, 麦克风
I'm currently working through this code snippet from a design patterns book:
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));
}
}
This deals with wiring up DomainEvents, and this particular code snippet is responsible allowing me to raise an event via the Raise
method on DomainEvents.
Here is the code in my Bootstrapper file:
public class ControllerRegistry : Registry
{
public ControllerRegistry()
{
ForRequestedType<IDomainEventHandlerFactory>().TheDefault.Is.OfConcreteType<StructureMapDomainEventHandlerFactory>();
ForRequestedType<IDomainEventHandler<OrderSubmittedEvent>>().AddConcreteType<OrderSubmittedHandler>();
}
}
When I go to access DomainEvents.Raise
from my Service layer (in this example, I'm raising the OrderSumittedEvent
), DomainEvents
is null
(when it should be set via StructureMap):
public class OrderService
{
public void Create(Order order)
{
DomainEvents.Raise(new OrderSubmittedEvent() { Order = order });
}
}
Unless I explicitly set the DomainEvents.DomainEventHandlerFactory
by hand to StructureMapDomainEventHandlerFactory
like this:
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 });
}
}
Below is the output of StrucutureMap using .WhatDoIHave()
, and it appears that StructureMap does have a configured instance of StructureMapDomainEventHandlerFactory
for type IDomainEventHandlerFactory
. Here is the dump:
================================================================================================================================================================================================================================================================================================================================================================================================
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
================================================================================================================================================================================================================================================================================================================================================================================================
I've used StructureMap, but I haven't used Setter Injection, nor have I had to deal with using StructureMap with static classes (if that even makes sense), so I'm a little lost as to why this code won't work.
Is it possible to use Setter Injection with a static implementation of a class like this?
Am I not using StructureMap properly?
Should StructureMap be responsible for creating the DomainEvents class as a Singleton, and I can get rid of the static implementation?
Thanks,
Mike
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不可以。只有可创建的类才有可能。
你不是。依赖注入涉及创建和提供实例。根据定义,静态类在代码中不可创建,因此不可注入。
看起来此设计的核心功能是使用单个实例,因此事件仅被触发一次。我不确定您想要什么设计模式,但在许多情况下,您可以用
Action
或Func
替换事件,并且如果您使用正确地使用单例生活方式,您可能可以注册一个可以在所有类之间共享的单个实例,而不是诉诸静态类。如果绝对需要静态事件,您可以在应用程序启动代码中注入 IDomainEventHandlerFactory 的实例,方法是解析该实例并在完成注册代码后手动设置它(在您的 组合根)。
为了确保您的应用程序不会通过多次调用 setter 或在设置之前使用它来滥用 setter,您可以在静态类中放置一些保护子句。
No. It is only possible with createable classes.
You are not. Dependency injection deals with creating and providing instances. By definition static classes are non-createable in code and therefore, non-injectable.
It looks like a core feature of this design is to use a single instance so the event is only fired once. I am not sure what design pattern you are going for, but in many cases you can substitute
Action<T>
orFunc<T>
for events, and if you use the singleton lifestyle properly you can probably register a single instance that can be shared between all of your classes rather than resorting to a static class.If the static event is absolutely required, you can inject an instance of IDomainEventHandlerFactory in your application startup code by resolving the instance and setting it manually after you have completed your registration code (in your composition root).
To ensure your application doesn't abuse the setter by calling it more than once or using it before it is set, you can put some guard clauses in your static class.