我在实现一些序列化/反序列化逻辑时遇到了一些问题。
我有几个类,每个类都采用不同类型的Request对象,所有类都实现了一个公共接口并继承了默认实现:
我认为这应该是:
请
interface IRequest
{
public String Action {get;set;}
}
class DefaultRequest : IRequest
{
public String Action {get;set;}
}
class LoginRequest : DefaultRequest
{
public String User {get;set;}
public String Pass {get;set;}
}
处理程序
interface IHandler<T>
{
public Type GetRequestType();
public IResponse HandleRequest(IModel model, T request);
}
class DefaultHandler<T> : IHandler<T> // Used as fallback if the handler cannot be determined
{
public Type GetRequestType()
{
return /* ....... how to get the Type of T? ((new T()).GetType()) ? .......... */
}
public IResponse HandleRequest(IModel model, T request)
{
/* ... */
}
}
class LoginHandler : DefaultHandler<LoginRequest>
{
public IResponse HandleRequest(IModel mode, LoginRequest request)
{
}
}
调用
class Controller
{
public ProcessRequest(String action, String serializedRequest)
{
IHandler handler = GetHandlerForAction(action);
IRequest request = serializer.Deserialize<handler.GetRequestType()>(serializedRequest);
handler(this.Model, request);
}
}
我认为甚至可能吗?
我目前的解决方案是每个处理程序获取序列化的字符串,并且自己负责反序列化。这不是一个好的解决方案,因为它包含重复的代码,每个HandleRequest方法的开头看起来都一样(FooRequest request = Deserialize(serializedRequest); + try / catch和其他错误处理失败的反序列化)。
无法将预期类型信息嵌入到序列化数据中。
感谢任何提示。
答案 0 :(得分:2)
我可能完全误解了这个问题,但我只是在看这里的示例代码和评论......
public Type GetRequestType()
{
return /* ....... how to get the Type of T? ((new T()).GetType()) ? */
}
您真的只是想获取T
类型参数的运行时类型吗?如果是这样,那么只需使用typeof
。
public Type GetRequestType()
{
return typeof(T);
}
请注意,我稍后会查看其他代码:
class Controller
{
public ProcessRequest(String action, String serializedRequest)
{
IHandler handler = GetHandlerForAction(action);
IRequest request =
serializer.Deserialize<handler.GetRequestType()>(serializedRequest);
handler(this.Model, request);
}
}
你不能这样做。你不能只将Type
作为泛型类型参数粘贴在那里,它不会编译。如果您有一个实际的运行时Type
实例,您需要将其用作通用参数,那么唯一的方法是使用反射:
Type serializerDef = typeof(MySerializer<>);
Type serializerType = serializerDef.MakeGenericType(requestType);
MethodInfo method = serializerType.GetMethod("Deserialize",
BindingFlags.Instance | BindingFlags.Public);
IRequest request = (IRequest)method.Invoke(serializer, serializedRequest);
这很丑陋,但是当你尝试将泛型类型与反射混合时就是这样。
哦,这假设“序列化器”本身是一般类型;如果您尝试在非泛型类型上调用泛型方法,正如原始代码所示,那么这会变得更加麻烦。