I have a problem with Chain of Responsibility pattern. All handlers implements this class:
/// <summary>
/// Chain of Responsibility pattern
/// </summary>
abstract public class ChainHandler
{
protected LogWrapper Log;
protected ChainHandler successor;
/// <summary>
/// SetSuccessor
/// </summary>
private void SetSuccessor(ChainHandler successor)
{
this.successor = successor;
}
protected oAPI NotImplemented
{
get { return new oAPI(HTTPCodes.NotImplemented); }
}
/// <summary>
/// Set Successor to the end of chain
/// </summary>
/// <param name="successor">Handler</param>
public void Add(ChainHandler successor)
{
if (this.successor == null) SetSuccessor(successor);
else
{
this.successor.Add(successor);
}
}
protected oAPI ReferToSuccessor (iAPI request)
{
if (successor != null) return successor.HandleRequest(request);
return NotImplemented;
}
/// <summary>
/// output API builder
/// </summary>
/// <param name="code">HTTP code</param>
/// <returns></returns>
protected oAPI RB(HTTPCodes code, string messsage = null, string data = null, bool hasError = false)
{
return new oAPI(Shared.User, code, message) { Data = data, HasError = hasError };
}
/// <summary>
/// Serializer (JSON)
/// </summary>
public Func<object, string> Serializer { get; set; }
/// <summary>
/// Handle request
/// </summary>
/// <param name="request">request</param>
/// <returns>result</returns>
public abstract oAPI HandleRequest(iAPI request);
}
Then I implement DocHandler
public class DocHandler:ChainHandler
{
public DocChain()
{
Log = new LogWrapper(this);
}
public override oAPI HandleRequest(iAPI request)
{
switch (request.Comand)
{
case iAPI.Target.GetModel:
return GetModel(request.DocID);
}
return ReferToSuccessor(request);
}
private Doc GetDoc(int id)
{
Log.Debug("get document by id: " + id);
using (var unit = UnitOfWork.Create())
{
var repository = unit.GetRepository<Doc>();
Doc doc = repository.Get(id);
if (doc == null)
{
Log.Error("Document not found");
throw new DocumentNotFoundException();
}
return doc;
}
}
public oAPI GetModel(int DocId)
{
var Model = GetDoc();
return RB(HTTPCodes.OK, data: Serializer(
Model));
}
}
And CloudHandler
public class CloudHandler:ChainHandler
{
private IDAVService _service;
private string RemoteRepository;
public CloudChain(IDAVService service)
{
Log=new LogWrapper(this);
_service=service;
}
public override oAPI HandleRequest(iAPI request)
{
switch (request.Comand)
{
case iAPI.Target.UploadModel:
return Upload(request.DocID,request.VersionID);
case iAPI.Target.DownloadModel:
return Download(request.VersionID, request.DocID);
}
return ReferToSuccessor(request);
}
public oAPI Upload(int DocID,int VersionID)
{
// Need to get model from DocHandler
var model = ???
service.Upload(model);
return RB(HTTPCodes.OK);
}
public oAPI Download(int DocID,int VersionID)
{
// Need to get model from DocHandler
var model = ???
service.Download(model);
return RB(HTTPCodes.OK);
}
}
And my problem in finding the best way to share methods and properties between handlers. Now I use static class SharedComponents where each handler delegate own method.
public static class SharedComponents
{
public static Func<int, Doc> GetDoc;
}
In DocHandler I delegate method SharedComponents.GetDoc = this.GetDoc;
and then use it in CloudHandler var Model = SharedComponents.GetDoc(docid)
. This is spagetti to write delegates to hundred of shared methods.
But how I tested this? I will must initialize all handlers (because A
uses method of B
and B
may use methods of C
etc.) to test one method in one handler. Horror!
I try to set shared methods as static to use like var Model = DocHandler .GetDoc(docid)
. But this solution breaking Dependency inversion principle. And if some shared method use context (like session
in UnitOfWork
) to I need in test initialise all handlers again!
Aucun commentaire:
Enregistrer un commentaire