2011-04-12 9 views
13

ドメインイベントをプロジェクトに導入しようとしています。コンセプトはあるUdi漢の記事で説明されて - 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 
     } 
    } 
} 

UPDATE れ、EventDispatcherがOK働いているエラー!手動でハンドラを登録し、ドメインイベントを発生させた場合は、それが動作します。アセンブリのスキャン/レジストレーションが私の問題です。 手動登録コード...

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

は、どのように私は彼らがこの

public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated> 

答えて

7

Peterが指摘したように、登録の問題はWhere()句にありました。

アセンブリをスキャンする場合Autofacが自動的にそれだけで用いても正しいだろうので、あなたは、指定したサービスに基づいてコンポーネントをフィルタリング:

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

パーフェクトニック!私はあなたの今後のコースを楽しみにしています! – CRG

+0

ああ、はい、よりスムーズです。私は15の担当者の強盗! –

+0

Heheあなたがそれを必要としているように、L.;)あなたは私の投票にもかかわらず。 –

0

のように見える与えられたすべてのIHandleDomainEvents<>のためのすべてのアセンブリをスキャンしない私はAutofacに慣れていないんだけど、私は、私は「信じますmは同様の問題を抱えていますが、autofacではなく、アーキテクチャDynamic generic interface castを持っています。

これはおそらくCovariance and Contravariance号です。

+0

おかげペドロは、私が行うにはいくつかのより多くの読書をしましたね! – CRG

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

こんにちはPeterさん、どの名前空間で 'IsClosingTypeOf'を見つけることができますか – CRG

+0

IsClosedTypeOfを意味しましたか?私はそれを試して、それは動作しませんでした。しかし、それは非常に有望に見えた!他のアイデアは非常に役に立つと思います。私はこれまであまりにも長い間これを乱してきました... – CRG

+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

関連する問題