动态将对象转换为基本类型

时间:2018-08-17 18:33:36

标签: c# serialization dynamic types polymorphism

假设我有一个类型未知的对象
object obj
我可以使用obj.GetType().BaseType来获取它的基本类型,但是如何继续将obj转换为该基本类型?

上下文:

在我的情况下,我正在编写一个Serialize方法,该方法使用类似反射的方式将任何对象序列化为字符串

public static string Serialize(this object obj)
{
    string _serialization;
    foreach (field in obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public))
    {
        _serialization += field.value
    }
    return _serialization;
}

尤其是我的问题是,您无法使用GetFields()从基本类型中获取私有字段,所以我要做的就是将field.value转换为它的基本类型以便能够访问这些字段并递归序列化obj的所有父类型。
所以我想做的基本上是

foreach (baseType in field.value.baseTypes)
{
    serialization += field.value.ConvertToBaseType().Serialize()
}

我能想到的只是Convert.ChangeType(object, Type),但我得到一个例外,说object需要实现IConvertible,而在我项目的所有内容中都不能实现IConvertible 。另外,我认为此方法适用于.net框架类型和值类型。

这篇文章中的所有代码都是用于重现我的情况的示例代码,因为它规模更大,我不能只在此处转储所有这些代码。

编辑: 这不是that post的副本,因为即使我的情况相似,我也有完全不同的问题。
根本没有直接解决我的问题的方法,所以我将其解决。

2 个答案:

答案 0 :(得分:2)

不,您不能在执行时更改对象的类型,也没有内置的说法:“创建基本类型的新对象,而是从派生类型的该实例复制所有字段值。 ”

但是我真的不认为您需要-至少不需要像您所说的那样做:

  

特别是我的问题是,您无法使用GetFields()从基本类型中获取私有字段

是的-您只需要确保您同时要求非公开字段和公开字段即可。以下示例显示了层次结构中的所有字段,包括特定实例的值:

using System;
using System.Reflection;

class Base
{
    private int x = 10;    
}

class Derived : Base
{
    private int y = 20;
}

class Program
{
    static void Main()
    {
        object instance = new Derived();
        var type = instance.GetType();
        while (type != null)
        {
            Console.WriteLine($"Fields in {type}:");
            var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            foreach (var field in fields)
            {
                Console.WriteLine($"{field.Name}: {field.GetValue(instance)}");
            }
            type = type.BaseType;
        }
    }
}

此代码的输出是:

Fields in Derived:
y: 20
Fields in Base:
x: 10
Fields in System.Object:

请注意,x是基类中的私有字段,但仍会根据需要显示在输出中。

因此,您的Serialize方法需要一个类似的循环来遍历完整的类层次结构,对所有类型的所有字段进行序列化。 (我注意到,在序列化中还有很多其他复杂的事情要考虑,例如引用标识处理和循环,但这是另一回事。如果您可以编写自己的序列化程序代码而逃脱,我强烈建议您这样做。)

答案 1 :(得分:1)

Type tt = typeof (obj).BaseType;

foreach (FieldInfo fi in  tt.GetFields())
  {
      fi.GetValue(obj);
  }