:
private static readonly Dictionary<Type, Func<IRequestHandler>> _strategyGetter = new Dictionary<Type, IRequestHandler>()
{
{typeof(ActualRequest),() => new ActualRequestHandler()},
{typeof(AnotherRequest),() => new AnotherRequestHandler()}
};
そして最後に、あなたのグローバルコード:シンプルな構成は、外部プロセッサクラスの静的辞書可能性が
// Define a weakly typed interface, to be called
// by the invoking code.
public interface IRequestHandler
{
public string HandleRequest(string xmlRequest);
}
// Defines a generic handler, accepting two type parameters, one
// for the request, one for the response.
public abstract class RequestHandler<RequestType, ResponseType> : IRequestHandler
{
public XmlSerializer GetRequestSerializer()
{
return GetSerializer(typeof(RequestType));
}
public XmlSerializer GetResponseSerializer()
{
return GetSerializer(typeof(ResponseType));
// an alternative, depending upon your deserialization library,
// could be:
// return GetSerializer<ResponseType>();
}
public XmlSerializer GetSerializer(Type dataType)
{
... resolve based on type.
}
public string HandleRequest(string xmlRequest)
{
if (request == null) throw new ArgumentNullException("request");
var requestSerializer = GetRequestSerializer();
var typedRequest = requestSerializer.Deserialize(xmlRequest) as RequestType;
// response is a ResponseType
var response = ProcessRequest(typedRequest);
var responseSerializer = GetResponseSerializer();
return responseSerializer.Serialize(response);
}
protected abstract ResponseType ProcessRequest(RequestType request);
}
// One handler implementation
// you can just declare the class and RequestHandler inheritance,
// and then right click and ask Visual Studio to "Implement abstract members"
public class ActualRequestHandler : RequestHandler<ActualRequest, ActualResponse>
{
protected ActualResponse ProcessRequest(ActualRequest request)
{
// ... do your processing
}
}
// One handler implementation
public class AnotherRequestHandler : RequestHandler<AnotherRequest, AnotherResponse>
{
protected AnotherResponse ProcessRequest(AnotherRequest request)
{
// ... do your processing
}
}
要求パターンを型付きハンドラにリダイレクトするためにコマンドパターンで責任のチェーン(COR)のフレーバを使用します。
デザインベーススケルトン -
abstract class RequestBase { }
abstract class ResponseBase { }
/// <summary>
/// Base class which will handle the request if the derived type is responsible otherwise
/// send request to success handler in chain.
/// </summary>
internal abstract class HandlerBase<TRequest, TResponse> // contraints
where TResponse : ResponseBase
where TRequest : RequestBase
{
HandlerBase<TRequest, TResponse> nextHandler;
protected HandlerBase(HandlerBase<TRequest, TResponse> nextHandler)
{
this.nextHandler = nextHandler;
}
public TResponse Execute(TRequest request)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
try
{
if (this.IsResponsible(request))
return this.InternalExecute(request);
else
return this.nextHandler.InternalExecute(request);
}
catch (Exception exception)
{
// log exception and rethrow or convert then throw.
throw;
}
}
protected abstract TResponse InternalExecute(TRequest request);
protected abstract bool IsResponsible(TRequest request);
}
は今、例えば、あなたの具体的な要求と、それぞれのハンドラを実現します
class RequestA : RequestBase { }
class ResponseA : ResponseBase { }
class RequestB : RequestBase { }
class ResponseB : ResponseBase { }
internal class RequestAHandler : HandlerBase<RequestBase, ResponseBase>
{
public RequestAHandler(HandlerBase<RequestBase, ResponseBase> nextHandler) : base(nextHandler) { }
protected override RequestB InternalExecute(RequestBase request)
{
// do what ever RequestA handler shall do
throw new NotImplementedException();
}
protected override bool IsResponsible(RequestBase request)
{
return request is RequestA;
}
}
internal class RequestBHandler : HandlerBase<RequestBase, ResponseBase>
{
public RequestBHandler(HandlerBase<RequestBase, ResponseBase> nextHandler) : base(nextHandler) { }
protected override RequestB InternalExecute(RequestA request)
{
// do what ever RequestB handler shall do
throw new NotImplementedException();
}
protected override bool IsResponsible(RequestBase request)
{
return request is RequestB;
}
}
最後にすべてをまとめる。要求を操作する責任あるハンドラを呼び出すCOR基本クラスがあります。しかし、チェーンやハンドラを知っているディスパッチャが必要で、入ってくるリクエストを渡すことができます。
class Dispatcher
{
// cache chained instances of handlers
private static HandlerBase<RequestBase, ResponseBase> handler = RegisterHandlers();
public static ResponseBase Dispatch(RequestBase request)
{
return handler.Execute(request);
}
private static HandlerBase<RequestBase, ResponseBase> RegisterHandlers()
{
// Build chain
HandlerBase<RequestBase, ResponseBase> contextChain = new RequestAHandler(null);
contextChain = new RequestBHandler(contextChain);
// register new handlers here e.g.
// contextChain = new RequestXHandler(contextChain);
return contextChain;
}
}
使い方 - あなたはそれがボイラープレートコードのあまりだ考えるかもしれない
var response = (ResponseA)Dispatcher.Dispatch(new RequestA());
。しかし、フレームワークがどのように構築されているか(定型化されている) Xのリクエストタイプの新しいハンドラを追加する場合は、RequestX
、ResponseX
、RequestXHandler
を実装し、ディスパッチャに登録してください。
注 -システムを検証するユニットテストを作成します。私はオンラインのC#エディタでこのコードを書いた;)乾杯!
xmlを生成するためにserializeを使用する必要はありません。代わりに動的タグがある場合は、xmlElementまたはXElement(xml linq)のいずれかを使用してxmlを生成します。 – jdweng