Home

Awesome

protobuf-net-v2-for-ILRuntime

适配了ILRuntime的protobuf-net

该部分代码已在隔壁JEngine框架使用了大半年了,稳得很

注意

不要继承IExtensible,不要继承IExtensible,不要继承IExtensible!

用生成出来的C#文件!

使用前需要在ILRuntime加载AppDomain之前注册一下:

//Protobuf适配
PType.RegisterILRuntimeCLRRedirection(appdomain);

//CLR重定向
public void Register()
{
  //注册pb反序列化
  Type pbSerializeType = typeof(Serializer);
  var args = new[] {typeof(Type), typeof(Stream)};
  var pbDeserializeMethod = pbSerializeType.GetMethod("Deserialize", flag, null, args, null);
  appdomain.RegisterCLRMethodRedirection(pbDeserializeMethod, Deserialize_1);
  args = new[] {typeof(ILTypeInstance)};
  Dictionary<string, List<MethodInfo>> genericMethods = new Dictionary<string, List<MethodInfo>>();
  List<MethodInfo> lst = null;
  foreach (var m in pbSerializeType.GetMethods())
  {
      if (m.IsGenericMethodDefinition)
      {
          if (!genericMethods.TryGetValue(m.Name, out lst))
          {
              lst = new List<MethodInfo>();
              genericMethods[m.Name] = lst;
          }

          lst.Add(m);
      }
  }

  if (genericMethods.TryGetValue("Deserialize", out lst))
  {
      foreach (var m in lst)
      {
          if (m.MatchGenericParameters(args, typeof(ILTypeInstance), typeof(Stream)))
          {
              var method = m.MakeGenericMethod(args);
              appdomain.RegisterCLRMethodRedirection(method, Deserialize_2);
              break;
          }
      }
  }
}

/// <summary>
/// pb net 反序列化重定向
/// </summary>
/// <param name="__intp"></param>
/// <param name="__esp"></param>
/// <param name="__mStack"></param>
/// <param name="__method"></param>
/// <param name="isNewObj"></param>
/// <returns></returns>
private static unsafe StackObject* Deserialize_1(ILIntepreter __intp, StackObject* __esp,
    IList<object> __mStack, CLRMethod __method, bool isNewObj)
{
    AppDomain __domain = __intp.AppDomain;
    StackObject* ptr_of_this_method;
    StackObject* __ret = ILIntepreter.Minus(__esp, 2);

    ptr_of_this_method = ILIntepreter.Minus(__esp, 1);
    Stream source =
        (Stream) typeof(Stream).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack));
    __intp.Free(ptr_of_this_method);

    ptr_of_this_method = ILIntepreter.Minus(__esp, 2);
    Type type = (Type) typeof(Type).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack));
    __intp.Free(ptr_of_this_method);


    var result_of_this_method = Serializer.Deserialize(type, source);

    object obj_result_of_this_method = result_of_this_method;
    if (obj_result_of_this_method is CrossBindingAdaptorType adaptorType)
    {
        return ILIntepreter.PushObject(__ret, __mStack, adaptorType.ILInstance, true);
    }

    return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method, true);
}

/// <summary>
/// pb net 反序列化重定向
/// </summary>
/// <param name="__intp"></param>
/// <param name="__esp"></param>
/// <param name="__mStack"></param>
/// <param name="__method"></param>
/// <param name="isNewObj"></param>
/// <returns></returns>
private static unsafe StackObject* Deserialize_2(ILIntepreter __intp, StackObject* __esp,
    IList<object> __mStack, CLRMethod __method, bool isNewObj)
{
    AppDomain __domain = __intp.AppDomain;
    StackObject* ptr_of_this_method;
    StackObject* __ret = ILIntepreter.Minus(__esp, 1);

    ptr_of_this_method = ILIntepreter.Minus(__esp, 1);
    Stream source =
        (Stream) typeof(Stream).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack));
    __intp.Free(ptr_of_this_method);

    var genericArgument = __method.GenericArguments;
    var type = genericArgument[0];
    var realType = type is CLRType ? type.TypeForCLR : type.ReflectionType;
    var result_of_this_method = Serializer.Deserialize(realType, source);

    return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method);
}

限制

  1. ProtoMember标签只能有一个int字段,不能有其他的(某些情况可以,参考后面的链接),参考ILRuntime issue #593
  2. Property不能就{get;set;},轻则报错空引用,重则闪退

版本说明

支持的类型

暂不支持的类型

代码导出

支持C#文件和proto文件互转