また、Spring.NETなどのある種のIoCフレームワークを使用して、辞書を挿入することもできます。このように、新しいメッセージタイプを取得した場合、この中央ハブを再コンパイルする必要はありません。構成ファイルを変更するだけです。
待望の例:
Exampleという名前の新しいコンソールアプリを作成し、次を追加します。
using System;
using System.Collections.Generic;
using Spring.Context.Support;
namespace Example
{
internal class Program
{
private static void Main(string[] args)
{
MessageBroker broker = (MessageBroker) ContextRegistry.GetContext()["messageBroker"];
broker.Dispatch(null, new Type1EventArgs());
broker.Dispatch(null, new Type2EventArgs());
broker.Dispatch(null, new EventArgs());
}
}
public class MessageBroker
{
private Dictionary<Type, object> handlers;
public Dictionary<Type, object> Handlers
{
get { return handlers; }
set { handlers = value; }
}
public void Dispatch<T>(object sender, T e) where T : EventArgs
{
object entry;
if (Handlers.TryGetValue(e.GetType(), out entry))
{
MessageHandler<T> handler = entry as MessageHandler<T>;
if (handler != null)
{
handler.HandleMessage(sender, e);
}
else
{
//I'd log an error here
Console.WriteLine("The handler defined for event type '" + e.GetType().Name + "' doesn't implement the correct interface!");
}
}
else
{
//I'd log a warning here
Console.WriteLine("No handler defined for event type: " + e.GetType().Name);
}
}
}
public interface MessageHandler<T> where T : EventArgs
{
void HandleMessage(object sender, T message);
}
public class Type1MessageHandler : MessageHandler<Type1EventArgs>
{
public void HandleMessage(object sender, Type1EventArgs args)
{
Console.WriteLine("Type 1, " + args.ToString());
}
}
public class Type2MessageHandler : MessageHandler<Type2EventArgs>
{
public void HandleMessage(object sender, Type2EventArgs args)
{
Console.WriteLine("Type 2, " + args.ToString());
}
}
public class Type1EventArgs : EventArgs {}
public class Type2EventArgs : EventArgs {}
}
そしてapp.configファイル:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<object id="messageBroker" type="Example.MessageBroker, Example">
<property name="handlers">
<dictionary key-type="System.Type" value-type="object">
<entry key="Example.Type1EventArgs, Example" value-ref="type1Handler"/>
<entry key="Example.Type2EventArgs, Example" value-ref="type2Handler"/>
</dictionary>
</property>
</object>
<object id="type1Handler" type="Example.Type1MessageHandler, Example"/>
<object id="type2Handler" type="Example.Type2MessageHandler, Example"/>
</objects>
</spring>
</configuration>
出力:
タイプ1、Example.Type1EventArgs
タイプ2、Example.Type2EventArgs
イベントタイプにハンドラーが定義されていません:EventArgs
ご覧のとおりMessageBroker
、ハンドラーについては知りません。また、ハンドラーはについて知りませんMessageBroker
。すべてのマッピングはapp.configファイルで行われるため、新しいイベントタイプを処理する必要がある場合は、それを構成ファイルに追加できます。これは、他のチームがイベントタイプとハンドラーを定義している場合に特に便利です。それらは、dllにコンパイルするだけで、デプロイメントにドロップして、マッピングを追加するだけです。
MessageHandler<>
実際のハンドラーをキャストできないため、ディクショナリにはオブジェクト型の値がありMessageHandler<EventArgs>
ます。そのため、少しハックする必要がありました。ソリューションはまだクリーンであり、マッピングエラーを適切に処理すると思います。このプロジェクトではSpring.Core.dllも参照する必要があることに注意してください。ライブラリはここにあり、ドキュメントはここにあります。依存性注入の章はこれに関連しています。また、これにSpring.NETを使用する必要がある理由はありません。ここで重要なのは依存性注入です。どういうわけか、タイプaからxのメッセージを送信するようにブローカーに指示する必要があります。依存性注入にIoCコンテナーを使用することは、ブローカーにxについて知らないようにするための良い方法です。
IoCとDIに関連するその他のSOの質問: