上記のVisitorアプローチが好きです。ただし、楽しみのために、VS2008およびVS2010でT4を使用してコードの冗長性を減らす方法について少し説明します。
冗長性は、Visitメソッドが必要な各メッセージに由来します。また、各メソッドには、Acceptの単純ですが冗長な実装が必要です。「繰り返さないでください」に近づく1つの方法は、T4を使用してコードを生成することです。
次のサンプルをテストするには、VSにクラスを追加しますが、拡張子を.csから.ttに変更します。これで、.ttファイルに接続された.ttファイルと.csファイルの2つのファイルが取得されます。
.ttファイルは、.csファイルを生成するテンプレートです。当時、それらは同一です。
これを.ttファイルのコンテンツとして使用します。
<#@ template language="C#" #>
<#
// On VS2008 change C# above to C#v3.5
// -----------------------------------------------------
// Here we declare our different message types
var messageTypes = new []
{
"Simple",
"Complex",
"Other",
};
// -----------------------------------------------------
#>
namespace MessageProcessor
{
partial interface IMessageVisitor
{
<#
// Let's generate all message visitor methods
foreach (var messageType in messageTypes)
{
#>
void Visit (<#=messageType#>Message message);
<#
}
#>
}
abstract partial class Message
{
public abstract void Accept (IMessageVisitor visitor);
}
<#
// Let's generate all message types
foreach (var messageType in messageTypes)
{
#>
sealed partial class <#=messageType#>Message : Message
{
public override void Accept (IMessageVisitor visitor)
{
visitor.Visit (this);
}
}
<#
}
#>
}
これにより、次のようなCSファイルが生成されます。
namespace MessageProcessor
{
partial interface IMessageVisitor
{
void Visit (SimpleMessage message);
void Visit (ComplexMessage message);
void Visit (OtherMessage message);
}
abstract partial class Message
{
public abstract void Accept (IMessageVisitor visitor);
}
sealed partial class SimpleMessage : Message
{
public override void Accept (IMessageVisitor visitor)
{
visitor.Visit (this);
}
}
sealed partial class ComplexMessage : Message
{
public override void Accept (IMessageVisitor visitor)
{
visitor.Visit (this);
}
}
sealed partial class OtherMessage : Message
{
public override void Accept (IMessageVisitor visitor)
{
visitor.Visit (this);
}
}
}
なぜこれは冗長性が低いのですか?新しいメッセージを追加したいときはいつでも、それをテンプレートに追加するだけだからです。
var messageTypes = new []
{
"Simple",
"Complex",
"Other",
"YetAnotherOne",
};
メッセージには異なるペイロードが必要なため、すべてのメッセージが部分的に生成されることに注意することが重要です。これは別のファイルで指定されており、次のようになります。
partial class SimpleMessage
{
public string Name;
}
partial class ComplexMessage
{
public XmlDocument Xml;
}
T4のサウンドが好きな人は、このブログをチェックしてください:http ://www.olegsych.com/2008/09/t4-tutorial-creatating-your-first-code-generator/