I'm still working on my general-purpose logging component which should handle any kind of an object
and convert it ("serialize" it) to a string.
Works quite well so far - except for one requirement: I should be able to identify the base type of a given object (if one exists), and also list that base type's properties separately.
Basically, I have a method something like this:
public string LogObject(object myObject)
and now I'd like to check to see if this object's type has a base class, and if so - get the properties of my object, "downcast" to its base type.
The checking of the base type isn't hard:
Type baseType = myObject.GetType().BaseType;
but how do I downcast myObject
to an object of type baseType
now?
I tried several things, like:
object baseObject = Convert.ChangeType(myObject, baseType);
but that requires my object type to implement IConvertible
which I cannot possible require from all my objects...
Any other way?
Those of course don't work....
object baseObject = myObject as baseType;
object baseObject = (baseType)myObject;
Any other way I'm not thinking of?
Update: I had already thought about doing it by
myObject
into allProperties
myObject
type into declaredProperties
(BindingFlag.Declared
) baseProperties
by subtracting the declaredProperties
from allProperties
but that just seems a bit excessive on the reflection - not sure if that'll perform decently....
In class-based programming, downcasting or type refinement is the act of casting a reference of a base class to one of its derived classes.
A dynamic cast expression is used to cast a base class pointer to a derived class pointer. This is referred to as downcasting.
Downcasting is not allowed without an explicit type cast. The reason for this restriction is that the is-a relationship is not, in most of the cases, symmetric. A derived class could add new data members, and the class member functions that used these data members wouldn't apply to the base class.
The C++ built-in static_cast can be used for efficiently downcasting pointers to polymorphic objects, but provides no error detection for the case where the pointer being cast actually points to the wrong derived class.
Use BindingFlags.DeclaredOnly to get members declared on a specific type only. Also, even if you do not use this flag, every returned ProperyInfo has a DeclaredType property which lists the type declaring the property.
The only reason I can think of for using DeclaredOnly is if you want better control over the result set, e.g. to filter out virtual properties that have been overridden in subclasses.
PS: Using a library like Fasterflect can make tasks like this a breeze ;)
Solution:
If anyone is interested - based on Oded's and Morten's comments, this is the solution I ended up using:
// get all the properties of "myObject"
List<PropertyInfo> propertyInfoList = new List<PropertyInfo>(myObject.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public));
// get the object's type and its base type
Type objectType = objectToLog.GetType();
Type baseType = objectToLog.GetType().BaseType;
// if a baseType exists ...
if (baseType != null)
{
// get the list of properties that are *not* defined directly in "myObject" -
// those are all the properties defined in the immediate and possible other base types
List<PropertyInfo> baseProperties = propertyInfoList.Where(x => x.DeclaringType != objectType).ToList();
// process those base properties
// after processing, remove the base properties from the list of "all" properties to get just those
// properties that are defined directly on the "myObject" type
List<PropertyInfo> declaredProperties = propertyInfoList.Except(baseProperties);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With