Reputation: 156
Let's say I have an object of unknown type
object obj
I can get it's base type with obj.GetType().BaseType
, but how do I proceed to convert obj
to this base type?
Context:
In my case, I'm writing a Serialize method which serliaizes any object to a string using reflection looking sort of like this
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;
}
My problem in particular is that you can't get private fields from the base type with GetFields()
, so what I want to do is to convert field.value
to it's base type to be able to access those fields and recursively serialize all parent types of obj
.
So what I want to be able to do is basically
foreach (baseType in field.value.baseTypes)
{
serialization += field.value.ConvertToBaseType().Serialize()
}
All I could think of is Convert.ChangeType(object, Type)
but I get an exception saying object
needs to implement IConvertible
, and implementing IConvertible
in everything in my project is not an option. Also I suppose this method was intended for .net framework types and value types.
All code in this post is sample code used to recreate my situation as it is on a much larger scale and I can't just dump all that code here.
Edit:
This is not a duplicate of that post as I have an entirely different question even if my context is similar.
There simply isn't a direct solution to my problem so I'll close this.
Upvotes: 1
Views: 828
Reputation: 1499770
No, you cannot change the type of an object at execution time, nor is there any built in way of saying "Create a new object of the base type, but copy all the field values from this instance of a derived type."
But I really don't think you need to - at least not from what you've described as your reason for wanting to do so:
My problem in particular is that you can't get private fields from the base type with GetFields()
Yes you can - you just need to make sure you ask for non-public fields as well as public ones. Here's an example showing all the fields in the hierarchy, including their values for a particular instance:
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;
}
}
}
The output of this code is:
Fields in Derived:
y: 20
Fields in Base:
x: 10
Fields in System.Object:
Note that x
is a private field in the base class, and yet it's still shown in the output, as desired.
So your Serialize
method needs a similar loop to go through the complete class hierarchy, serializing all the fields from all the types. (I'd note that there's a lot of other complex stuff to consider in serialization, such as reference identity handling and cycles, but that's a different matter. If you can get away without writing your own serializer code, I strongly suggest you do so.)
Upvotes: 3
Reputation: 4313
Type tt = typeof (obj).BaseType;
foreach (FieldInfo fi in tt.GetFields())
{
fi.GetValue(obj);
}
Upvotes: 1