我正在尝试将域事件引入项目中。这个概念在Udi Dahan的帖子中描述 - http://www.udidahan.com/2009/06/14/domain-events-salvation/
这是域事件代码
public interface IDomainEvent { }
public interface IHandleDomainEvents<T> where T : IDomainEvent
{
void Handle(T args);
}
public interface IEventDispatcher
{
void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent;
}
public static class DomainEvents
{
public static IEventDispatcher Dispatcher { get; set; }
public static void Raise<TEvent>(TEvent eventToRaise) where TEvent : IDomainEvent
{
Dispatcher.Dispatch(eventToRaise);
}
}
最重要的部分是IEventDispatcher实现,它将域事件与引发事件时发生的任何事件分离开来。诀窍是通过容器连接这个耦合。这是我的尝试
注册所有域事件处理程序的代码....
var asm = Assembly.GetExecutingAssembly();
var handlerType = typeof(IHandleDomainEvents<>);
builder.RegisterAssemblyTypes(asm)
.Where(t => handlerType.IsAssignableFrom(t)
&& t.IsClass
&& !t.IsAbstract)
.AsClosedTypesOf(handlerType)
.InstancePerLifetimeScope();
解析调度程序中的所有事件处理程序。问题是没有解决处理程序。
public class EventDispatcher : IEventDispatcher
{
private readonly IContainer _container;
public EventDispatcher(IContainer container)
{
_container = container;
}
public void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent
{
var handlers = _container.Resolve<IEnumerable<IHandleDomainEvents<TEvent>>>().ToList();
handlers.ForEach(handler => handler.Handle(eventToDispatch));
}
}
所以我没有正确注册事件处理程序或者没有解决它们。 如何检查注册是否有效?
处理程序的示例代码
public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated>
{
private readonly IConfig _config;
public SendWebQuestionToCSO(IConfig config)
{
_config = config;
}
public void Handle(JobNoteCreated args)
{
var jobNote = args.JobNote;
using(var message = new MailMessage())
{
var client = new SmtpClient {Host = _config.SmtpHostIp};
message.From = new MailAddress(_config.WhenSendingEmailFromWebProcessUseThisAddress);
...... etc
}
}
}
更新 经过一些试验和错误后,EventDispatcher正常工作!如果我手动注册一个处理程序,然后触发域事件它可以工作。装配扫描/注册是我的问题。 手动注册码......
builder.RegisterType<SendWebQuestionToCSO >().As<IHandleDomainEvents<JobNoteCreated>>();
所以如何扫描所有IHandleDomainEvents<>
的所有程序集,因为它们看起来像这样
public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated>
答案 0 :(得分:8)
正如彼得所指出的那样,注册问题与您的Where()
条款有关。
扫描程序集时,Autofac会根据您指定的服务自动过滤组件,因此只使用以下内容同样正确:
builder.RegisterAssemblyTypes(asm)
.AsClosedTypesOf(handlerType)
.InstancePerLifetimeScope();
答案 1 :(得分:1)
程序集扫描代码中的问题是您使用IsAssignableFrom
时的问题。过滤器会询问:“是否可以将SendWebQuestionToCSO
的实例分配给IHandleDomainEvents<>
的变量?”
答案显然是“不”,因为你永远不会有一个开放泛型类型的变量。
技巧是检查每种类型实现的接口,并检查它们是否正在关闭开放的通用接口类型。这是一个经过修改的扫描仪:
var asm = Assembly.GetExecutingAssembly();
var handlerType = typeof(IHandleDomainEvents<>);
builder.RegisterAssemblyTypes(asm)
.Where(t => t.GetInterfaces().Any(t => t.IsClosedTypeOf(handlerType)))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
答案 2 :(得分:0)
我不熟悉Autofac,但我相信我遇到了类似的问题,不是使用autofac而是使用架构Dynamic generic interface cast。