I'm building an http handler at work which has about 6 methods and I'm trying to figure out what design pattern will work the best for my needs:
What's done already (Only an example to make this more clear, methods are not real, but the main concept is there):
#region interfaces
public interface IDateRange
{
DateTime StartDate { get; set; }
DateTime EndDate { get; set; }
}
public interface ISomeMoreParams
{
int Param1 { get; set; }
int Param2 { get; set; }
}
public interface IBaseParams
{
string UserName { get; set; }
string CompanyName { get; set; }
}
public interface IClassMethod : IBaseParams
{
void ExecuteLogic(HttpContext context);
}
#endregion
#region FactoryClass
public static class ClassMethodFactory
{
public static IClassMethod GetInstance(string methodName)
{
switch(methodName)
{
case "MethodA":
return new MethodA();
case "MethodB":
return new MethodB();
case "MethodC":
return new MethodC();
}
throw new NotImplementedException(string.Format("{0} is not implemented", methodName));
}
}
#endregion
#region Class methods
public class MethodA : IClassMethod, IDateRange
{
string UserName { get; set; }
string CompanyName { get; set; }
DateTime StartDate { get; set; }
DateTime EndDate { get; set; }
public void ExecuteLogic(HttpContext context)
{
// Do MethodA
}
}
public class MethodB : IClassMethod, ISomeMoreParams
{
string UserName { get; set; }
string CompanyName { get; set; }
int Param1 { get; set; }
int Param2 { get; set; }
public void ExecuteLogic(HttpContext context)
{
// Do MethodB
}
}
public class MethodC : IClassMethod, IDateRange, ISomeMoreParams
{
string UserName { get; set; }
string CompanyName { get; set; }
DateTime StartDate { get; set; }
DateTime EndDate { get; set; }
int Param1 { get; set; }
int Param2 { get; set; }
public void ExecuteLogic(HttpContext context)
{
// Do MethodC
}
}
#endregion
#region HttpHandler
public IClassMethod method;
public void ProcessRequest(HttpContext context)
{
ProcessParams();
ExecuteLogic();
}
public ProcessParams()
{
var qs = HttpContext.Current.Request.QueryString;
method = ClassMethodFactory.GetInstance(qs["action"]);
if(method is IDateRange)
{
(method as IDateRange).StartDate = DateTime.Parse(qs["startDate"]);
(method as IDateRange).EndDate = DateTime.Parse(qs["endDate"]);
}
if(method is ISomeMoreParams
{
(method as ISomeMoreParams).Param1 = int.Parse(qs["param1"]);
(method as ISomeMoreParams).Param2 = int.Parse(qs["param2"]);
}
if(method is IBaseParams)
{
(method as IBaseParams).UserName = qs["UserName"];
(method as IBaseParams).CompanyName = qs["CompanyName"];
}
}
public ExecuteLogic()
{
method.ExecuteLogic();
}
#endregion
Now, the only part the I have a problem with, is the casting each time I want to see if the class method implements some parameter logic. I wish it would be more organized.
My thoughts: 1. Create for each parameter interface a parameter resolver class which would look like this:
#region Resolvers
public class DateRangeResolver
{
public void Resolve(IDateRange dateRangeClass)
{
var qs = HttpContext.Current.Request.QueryString;
dateRangeClass.StartDate = DateTime.Parse(qs["startDate"]);
dateRangeClass.EndDate = DateTime.Parse(qs["endDate"]);
}
}
public class SomeMoreParamsResolver
{
public void Resolve(ISomeMoreParams someMoreParamsClass)
{
var qs = HttpContext.Current.Request.QueryString;
someMoreParamsClass.Param1 = int.Parse(qs["param1"]);
someMoreParamsClass.Param2 = int.Parse(qs["param2"]);
}
}
public class BaseParamsResolver
{
public void Resolve(IBaseParams baseParamsResolver)
{
// Do resolve
}
}
#endregion
Then I change the code to fit the new approach:
#region interfaces
// ...
public interface IClassMethod : IBaseParams
{
void ProcessParams();
void ExecuteLogic();
}
// ...
#endregion
#region Class methods
// ...
public class MethodA : IClassMethod, IDateRange
{
// params
public void ProcessParams()
{
new BaseParamsResolver().Resolve(this);
new DateRangeResolver().Resolve(this);
}
public void ExecuteLogic()
{
// Do MethodA
}
}
public class MethodB : IClassMethod, ISomeMoreParams
{
// params
public void ProcessParams()
{
new BaseParamsResolver().Resolve(this);
new SomeMoreParams().Resolve(this);
}
public void ExecuteLogic()
{
// Do MethodB
}
}
public class MethodC : IClassMethod, IDateRange, ISomeMoreParams
{
// params
public void ProcessParams()
{
new BaseParamsResolver().Resolve(this);
new DateRangeResolver().Resolve(this);
new SomeMoreParams().Resolve(this);
}
public void ExecuteLogic(HttpContext context)
{
// Do MethodC
}
}
// ...
#endregion
#region HttpHandler
// ...
public void ProcessParams()
{
method.ProcessParams();
}
//...
#endregion
Now, my problem is that if I don't call the right resolvers on the ProcessParams of each class method, I would get an exception at runtime and not on debug, which means, I need to consider a new approach or change the existing approach to do so.
I had another idea, the idea is to add to each parameter interface its own resolver so when a class method implements the param interface it would also need to define the resolver for the interface.
This idea, although sounds better, still doesn't enforce the programmer to actually call these resolvers when executing the ProcessParams() function.
Now, after this long long explanation... is there a better way?