【问题标题】:C#: Determine Type for (De-)SerializationC#:确定(反)序列化的类型
【发布时间】:2011-02-17 20:09:21
【问题描述】:

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

我有几个类,每个类都采用不同类型的 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 和其他反序列化失败的错误处理)。

将类型信息嵌入到序列化数据中是不可能的,也不是有意的。

感谢任何提示。

【问题讨论】:

    标签: c# serialization type-conversion


    【解决方案1】:

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

    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);
    

    这很丑陋,但是当您尝试将泛型类型与反射混合时就是这样。

    哦,这假设“序列化器”本身是一个泛型类型;如果您尝试在 非泛型 类型上调用泛型 方法,如原始代码所示,那么这将变得更加麻烦。

    【讨论】:

    • 这是解决方案的一部分并且有很大帮助(尽管我现在觉得很愚蠢,因为我知道 typeof() 但不知何故没记住它),但调用部分仍然存在问题。无论如何,感谢您的帮助,将朝着这个方向进一步挖掘。
    • 再次感谢,看来我将不得不寻找另一种方法,因为我试图避免反射,因为它通常会严重损害可读性和可维护性,这是我真正关心的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    相关资源
    最近更新 更多