在运行时更改C#中字段的类型

时间:2009-11-09 17:34:01

标签: c# reflection serialization class-hierarchy

我有一个类的现有层次,比如说:

Business
  - Division
    - ProjectTeam
      - Employee

这些类通过反序列化实例化。

但是,现在我需要在Employee中为库的特定用户公开额外的字段,即如下所示:

SpecialBusiness (extends Business)
  - Division
    - ProjectTeam
      - SpecialEmployee (extends Employee)
        - Degree

问题是,我不能只创建一个扩展'Business'的课程,因为我想要的是'Employee'类。

我认为有两种选择:

  1. 将'herarchy'与'Special'类复制。这意味着每个“特殊”类都将包含原始类的集合以及新“特殊”类的集合。

    SpecialBusiness
      - Division AND SpecialDivision (extends Division)
        - ProjectTeam AND SpecialProjectTeam (extends ProjectTeam)
          - Employee AND SpecialEmployee (extends Employee)
            - Degree
    
  2. 以某种方式在运行时将'Employee'重新键入'SpecialEmployee'以进行反序列化。知道我可以将所有'Employee'对象从SpecialBusiness转换为代码库中的'SpecialEmployee'(可能使用辅助方法使其显而易见)。

  3. 关于如何处理这个问题的任何想法?

7 个答案:

答案 0 :(得分:1)

您无法在运行时更改字段的类型。

那就是说,如果你想做什么,为什么不能只扩展员工呢? Polymorphism声明您可以将子类型的对象插入其超类型的字段中?为什么需要重写父对象?

答案 1 :(得分:1)

嗯,我不完全确定它是否适合您的情况,但请查看我对this question的回答。您可以从Decorable派生Division和Employee类,并从Decorator<Division>Decorator<Employee>派生SpecialDivision和SpecialEmployee。

答案 2 :(得分:1)

我不知道你现在是否可以做,但是整个对象结构应该使用接口而不是具体的类。

答案 3 :(得分:1)

大多数序列化框架,例如XmlSerializer和BinaryFormatter提供了以自定义方式反序列化流的方法,因此您可以拥有更新的/新的层次结构并将旧流反序列化到其中。你使用什么样的序列化框架?

答案 4 :(得分:1)

为什么不能使用反序列化源来实例化运行时所需的类?

答案 5 :(得分:1)

当XML将实际对象类型声明为:

  <Employees>
    <Employee>
      <Name>Bob</Name>
    </Employee>
    <Employee xsi:type="SpecialEmployee">
      <Name>Carol</Name>
      <Degree>Chief</Degree>
    </Employee>
  </Employees>

至少在从声明的类型(这里是Employee [] Employees)推迟时,XMLSerializer在反序列化时很好地支持多态,因为它将创建一个Name =“Carol”和Degree =“Chief”的SpecialEmployee;鉴于SpecialEmployee派生自Employee,并且XMLSerializer被告知。
这可以通过XmlInclude属性完成,也可以在创建XMLSerializer时提供专用类型。

答案 6 :(得分:0)

一种可能的解决方案(假设选择的反序列化方法允许私有字段序列化):

使用问题中的方法1(即单独的层次结构)并将类的扩展版本存储在私有字段中。反序列化后,使用扩展版本更新常规公共非扩展字段,并包含一个返回这些字段的强制转换版本的方法。

SpecialProjectTeam
  - (private) SpecialEmployees
  - (public) Employees
  - (public) GetSpecialEmployees (returns Employees field cast as SpecialEmployees)