【问题标题】:Get field and property's type of a class recursively递归获取类的字段和属性类型
【发布时间】:2019-04-24 16:52:38
【问题描述】:

假设我有一个这样的课程:

public class Class1 {
    public int x1;
    public Class2 x2;
    public double x3;
}

public class Class2 {
    public int y1;
    private int x2;
}

有没有办法获取Class1所有可序列化成员的所有类型信息(我认为它的所有公共字段和属性都没有明确声明私有成员)?

例如,我想创建这样一个类型树:

<Class1>
    <x1>int</x1>
    <x2>Class2</x2>
        <Class2>
            <y1>int</y1>
        </Class2>
    <x3>double</x3>
 </Class1>

除非该成员是原子类型(如intdoubleList 和所有系统定义的类型),否则树将展开。

我的想法

我知道我可以使用reflectiondeep first search 来做这件事。但我发现事情可能会变得复杂,因为类可以是generic class。我担心是否有比generic class 更复杂的情况。

那么有没有比使用reflectiondeep first search 创建这棵树更好的解决方案?

【问题讨论】:

  • 当然可以,它会用到反射。但是这里的用例是什么?
  • 用例是:我想确保Class1的定义不会改变,那么Class1的改变意味着只有typename(如果成员有一个 XmlElement 属性,那么它的名字应该是所有 serializable 成员的 ElementName )不会改变。所以我想存储class1的所有类型和名称信息。
  • Reflection 非常适合您的需求。你为什么不使用它?泛型类的复杂性是什么?
  • @Caesium 哦,所以这是为了阻止肮脏的小手指改变课程。将其放入程序集或发布中的 nuget 中。无论如何,我认为您的问题是在反映和输出泛型类型参数时如何处理泛型类型
  • @TheGeneral 我不知道是什么意思,把它放在一个组件中......你能说清楚吗?

标签: c# generics recursion serialization reflection


【解决方案1】:

没有开箱即用的方法可以做到这一点,也没有太多的边界,只有泛型,有一些简单的方法可以获得泛型类型参数,你必须递归它们。

但是我认为您正在尝试以错误的方式解决此问题。

如果我对您的理解正确,您希望防止出现序列化问题。我会从不同的角度来看这个。

  1. 用接口装饰您的类以确保合同。
  2. 并且/命令将您的类/接口放入一个类库中,这样它们不太可能是缓冲的,甚至更进一步并消除它们。
  3. 如果您真的担心序列化问题,请使用基于合约的序列化程序,例如 DataContracts,如果更改会中断并且可以进行版本控制。

更新

  1. users 拥有需要序列化的类。

  2. 我使用 XmlSerializer 对其进行序列化和反序列化。

  3. 我要解决的问题是:

    • 首先,用户定义了上面的 Class1,它是 部署到机器 A 和机器 B。
    • 然后用户添加了一个公共 字段 x 进入 Class1,机器 A 的部署比 B 快。所以 机器 A 识别出新添加的 x。但是机器 B 的部署是 慢,所以机器B不知道x,那么序列化就会中断 用于机器 B。
    • 所以现在我要确保不再更改 传递给我的序列化程序的类。

那么你需要反思,没有我能想到的库可以满足你的需求。您将不得不深入研究泛型类型并回避,故事结束

【讨论】:

  • 1.用户拥有需要序列化的类。 2.我使用XmlSerializer对其进行序列化和反序列化。 3.我要解决的问题是:首先,用户定义Class1,如上,部署到机器A和机器B。然后用户在Class1中添加一个公共字段x,部署机器A 比 B 快。所以机器 A 识别了新添加的x。但是机器 B 的部署速度较慢,所以机器 B 不知道 x,那么机器 B 的序列化将中断。所以现在我要确保传递给我的序列化程序的类不再发生变化。
  • @Caesium 已更新,但是(不幸的是)您最初的问题是不使用反射,这是我可以在不编写反射代码的情况下给出的最佳答案
  • 如果唯一的边界情况是泛型,那我觉得问题没那么复杂……谢谢。
  • @Caesium 是的,如果你对反射代码有问题,就问一个新问题,它会在一瞬间排序
【解决方案2】:

我相信 FormatterServices.GetSerializableMembers 将返回所有可序列化成员,正如您最初在问题中提出的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    相关资源
    最近更新 更多