C# 将对象动态转换为基类型

C# 将对象动态转换为基类型,c#,serialization,dynamic,types,polymorphism,C#,Serialization,Dynamic,Types,Polymorphism,假设我有一个未知类型的对象 对象对象对象 我可以使用obj.GetType().BaseType获取它的基类型,但是如何继续将obj转换为此基类型 上下文: 在我的例子中,我正在编写一个序列化方法,它使用反射将任何对象序列化为字符串,看起来有点像这样 public static string Serialize(this object obj) { string _serialization; foreach (field in obj.GetType().GetFields(B

假设我有一个未知类型的对象
对象对象对象

我可以使用
obj.GetType().BaseType
获取它的基类型,但是如何继续将
obj
转换为此基类型

上下文:

在我的例子中,我正在编写一个序列化方法,它使用反射将任何对象序列化为字符串,看起来有点像这样

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 framework类型和值类型。

这篇文章中的所有代码都是用于重新创建我的情况的示例代码,因为它的规模要大得多,我不能把所有代码都放在这里

编辑: 这不是重复的,因为即使我的上下文相似,我也有一个完全不同的问题。

我的问题没有一个直接的解决方案,所以我将关闭它。

不,您不能在执行时更改对象的类型,也没有任何内置的方式来表示“创建基类型的新对象,但复制派生类型的此实例中的所有字段值。”

Type tt = typeof (obj).BaseType;

foreach (FieldInfo fi in  tt.GetFields())
  {
      fi.GetValue(obj);
  }
但我真的不认为你需要这样做——至少从你所描述的你想要这样做的原因来看是这样的:

我的问题是,无法使用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
方法需要一个类似的循环来遍历完整的类层次结构,序列化所有类型的所有字段。(我注意到,在序列化中有很多其他复杂的事情需要考虑,比如引用标识处理和循环,但这是另一回事。如果您不需要编写自己的序列化代码就可以脱身,我强烈建议您这样做。)现在我的问题是-我如何将
obj
转换为
tt
类型?@CharlieMalmqvist:你不需要-你只需要从基类型请求字段,然后从
obj
获取它们的值。我的回答给出了一个完整的例子。你是对的,但这并不能回答我的问题。我需要能够对我的方法进行转换,以使其正常工作,这是由于我迄今为止的工作方式。然而,如果没有人提出解决方案,我会接受这一点作为答案。@CharlieMalmqvist:没有办法进行这样的转换,在某些情况下这样做是完全不可行的——例如,如果基类是抽象的,你会期望发生什么?不能有类型为抽象类的对象。但是正如我在回答中所说的,你可以这样得到基类型的字段——正如我的回答和它的输出所示。我不认为这是完全不可行的,如果基类是抽象的,它只会抛出一个异常,就像当你试图创建抽象类型的实例时,
Activator.createInstance()
所做的那样。无论如何,这意味着我的问题没有真正的解决办法。无论如何,谢谢。不,这不会得到
Base
中的私有字段,只有int
派生的私有字段
@CharlieMalmqvist:运行我的代码时,输出是什么?对我来说,它是“派生中的字段:y:20基中的字段:x:10基中的字段。对象:”-这表明它确实在基类中提供了字段。@CharlieMalmqvist:我在答案的开头添加了“不,你不能更改对象的类型”这一位,但我不确定你为什么不愿意接受,反正你也不需要接受,你想这样做的最初原因其实不是问题。你认为你需要这样做还有其他原因吗?我不再需要这个了,我的问题已经解决了,谢谢你的帮助。我需要动态地沿着继承链向上移动,而不是像那篇文章的答案所建议的那样,并且海报也接受它。@CharlieMalmqvist:所以你动态地调用
BaseType
,如我的回答所示,你需要多少次就有多少次。你只向我们展示了伪代码,这并没有什么帮助。如果你能提供一个(就像我的回答那样)帮助你会更容易。