代码之家  ›  专栏  ›  技术社区  ›  Morfildur

C:确定(反)序列化的类型

  •  1
  • Morfildur  · 技术社区  · 15 年前

    我在实现一些序列化/反序列化逻辑时遇到了一些问题。

    我有几个类,每个类都采用不同类型的请求对象,它们都实现了一个公共接口并从默认实现继承:

    我认为应该是这样的:

    请求

    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请求=反序列化(serializedRequest);+在反序列化失败时尝试/catch和其他错误处理)。

    无法在序列化数据中嵌入类型信息,也不打算这样做。

    谢谢你的提示。

    1 回复  |  直到 15 年前
        1
  •  2
  •   Aaronaught    15 年前

    我可能完全误解了这个问题,但我只是在这里查看示例代码和注释…

    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 serializerDef = typeof(MySerializer<>);
    Type serializerType = serializerDef.MakeGenericType(requestType);
    MethodInfo method = serializerType.GetMethod("Deserialize",
        BindingFlags.Instance | BindingFlags.Public);
    IRequest request = (IRequest)method.Invoke(serializer, serializedRequest);
    

    它非常难看,但当你尝试将泛型类型与反射混合时,情况就是这样。

    哦,这假设“序列化程序”本身是一个泛型类型;如果您试图调用一个泛型 方法 在一 非泛型 正如原始代码所建议的那样,输入类型会变得更麻烦。