2011-04-12 52 views
13

我試圖將域事件引入到項目中。這個概念是在烏迪大漢的職位描述 - http://www.udidahan.com/2009/06/14/domain-events-salvation/在域事件中使用Autofac

這裏的域事件代碼

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 
     } 
    } 
} 

UPDATE 一些試驗後和錯誤的此事件正在ok了!如果我手動註冊一個處理程序,然後觸發該域名事件,它就可以工作程序集掃描/註冊是我的問題。 手動註冊碼...

builder.RegisterType<SendWebQuestionToCSO >().As<IHandleDomainEvents<JobNoteCreated>>(); 

那麼,如何掃描所有IHandleDomainEvents<>所有組件給予他們這個樣子

public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated> 

回答

7

正如彼得指出,登記問題是與您的Where()條款。

當掃描組件Autofac過濾自動根據您指定的服務組件,因此這將是同樣正確,只需使用:

builder.RegisterAssemblyTypes(asm) 
    .AsClosedTypesOf(handlerType) 
    .InstancePerLifetimeScope(); 
+0

完美的尼克!我期待着你即將到來的課程! – CRG 2011-04-13 12:09:47

+0

啊,是的,更平滑。儘管我搶了15個代表! – 2011-04-13 15:16:47

+0

嘿嘿就像你需要它,先生;)你仍然得到我的投票。 – 2011-04-13 20:47:50

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(); 
+0

嗨,彼得,在什麼名字空間我可以找到'IsClosingTypeOf' – CRG 2011-04-13 00:31:06

+0

你的意思是IsClosedTypeOf?我試了一下,但沒有奏效。但它看起來非常有希望!任何其他想法會非常有幫助我一直在搞這個太長時間了...... – CRG 2011-04-13 00:41:20

+0

我已經在code.google.com hg/src/Source/Autofac/Util/ReflectionExtensions.cs上查看了源代碼,並且擴展方法IsClosingTypeOf非常簡單,所以我複製了導致 - .Where(t => t.GetInterfaces()。Any(i => i.IsGenericType && i.GetGenericTypeDefinition()== handlerType))的代碼。這工作!最大的問題是版本2.4.5.724 .Net4中的擴展方法在哪裏? – CRG 2011-04-13 01:17:50