【发布时间】:2019-12-15 20:27:13
【问题描述】:
我正在编写一个用于序列化对象的 C# 代码生成器,以便通过网络发送它们。
起点是这样的(简化的):
public static partial class Serialization
{
public static void Serialize<T>(in T value, DataStream stream)
{
throw new NotImplementedException($"Don't know how to serialize type {typeof(T)}!");
}
public static void Deserialize<T>(out T target, DataStream stream)
{
throw new NotImplementedException($"Don't know how to deserialize type {typeof(T)}!");
}
}
现在,序列化代码生成器将为所有需要序列化的类型生成额外的非泛型 Serialize 和 Deserialize 方法,例如带有公共 float 字段 x、y 的结构 Vector3和z:
public static partial class Serialization
{
// automatically generated method
public static void Serialize(in Vector3 value, DataStream stream)
{
stream.Write(value.x);
stream.Write(value.y);
stream.Write(value.z);
}
// automatically generated method
public static void Deserialize(out Vector3 target, DataStream stream)
{
target.x = stream.ReadFloat();
target.y = stream.ReadFloat();
target.z = stream.ReadFloat();
}
}
开头显示的泛型方法仅用于在尚未(尚未)为某个类型生成序列化代码的情况下防止编译器错误。我需要编译代码,否则我无法对其使用反射。
目前我必须使用自定义EnableSerialization 属性标记需要序列化代码的类型。
理想情况下,生成器会查看编译后的代码(使用静态代码分析),识别可能传递给通用 Serialize 和 Deserialize 方法的类型,然后为这些类型生成代码。因此,例如,如果我的代码中有这个:
int x = 42;
Serialization.Serialize(x, new DataStream());
那么代码生成器应该选择int作为需要序列化代码的类型。
是否有这种努力的秘诀,或者 .NET 库或第三方库中是否有任何东西可以促进这种努力?
(我考虑过运行时代码生成,但我更喜欢将其作为预处理步骤。)
【问题讨论】:
-
不可能?也许不是?超级难,极其困难和复杂?当然。您必须反编译代码,并考虑通过它的所有可能 路径,并跟踪多种类型的
<T>用法,以便能够安全地 执行此操作。保留属性或其他一些标记概念。远,FAR,不值得尝试这样做,我不确定你是否能做到 100% 正确。 -
您的代码生成器是否可以为 all 类型正确创建序列化和反序列化代码?它可以在运行时、动态、即时生成中使用吗?
-
@LasseVågsætherKarlsen:它适用于相当简单的情况,即按顺序序列化所有字段就足够了(使用反射设置非公共字段)。我现在认为 ildasm.exe 工具可能有用。它显示了对我的泛型方法的所有调用,包括泛型参数。因此,也许在我的程序集上调用 ildasm.exe 并将输出转到文本文件,然后扫描文本文件以查找方法调用是一个好主意。
-
...当然,在可能的多种类型中跟踪泛型参数仍然是一个巨大的挑战...
标签: .net generics reflection code-generation analysis