C# - Casting a Reflection.PropertyInfo object to its Type
In my application, I have a Reflection.PropertyInfo
variable named 'property'. When I do a property.GetValue(myObject,null)
, the value is Master.Enterprise
. Enterprise is a class in my application. So, 'property' contains a reference to a class in my app.
At runtime, I would like to somehow cast 'property' to its type (Master.Enterprise
) so I can use it as if it were the class type.
I know this can be done because when I look at the code in the debugger, the debugger correctly casts 'property' to the type its refere开发者_JAVA百科ncing, and I can see all the properties of the Enterprise class in the debugger.
How might I go about doing this?
It sounds to me like you need to define an interface - you can then require that your property returns an object that implements that interface, and you will then be able to cast into that interface regardless of what class implements that interface:
IEnterprise enterprise = (IEnterprise)property.GetValue(myObject, null);
The only other option you have is to call methods and properties on the returned object using reflection - this is what the visual studio debugger is doing.
Master.Enterprise enterprise = (Master.Enterprise)property.GetValue(myObject,null);
or
Master.Enterprise enterprise = property.GetValue(myObject,null) as Master.Enterprise;
The first will throw an exception if the type is not compatible. The second will return null if not compatible.
In the future you can use dynamic
. For now I think you should use the solution with the interface.
If the type is unknown at compile time and you can't assume it implements an interface that IS known, you can't cast it to that type because c# is a statically typed language.
You'll be able to do this with c# 4.0 if you want to wait for it/use the beta, something like:
dynamic obj=property.GetValue(myObject,null);
obj.CallSomeMethod();
Note however that will internally just call reflection methods to figure out how to do that. You can do that today by extensive reflection calls yourself. If you give us more information about what specifically you want to do with that returned object, I'll be able to give you a more detailed answer.
If you have a string of the Type Name you can do something like this:
Assembly execAsm = Assembly.GetExecutingAssembly();
object instance = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(execAsm.FullName, "RipperWorkbench.Classes.LoadManager"); // the type name cam come from a variable or someplace else.
then you can cast it to the type you need
Master.Enterprise ent = obj as Master.Enterprise;
if (obj != null)
{
...
}
Or alternatively, have the object implement an interface: You have to be sure that the type is loaded into current AppDomain, otherwise the type can't be reflected.
Assembly asm = Assembly.GetExecutingAssembly();
// The executing assembly can change also; so you can load types from other assemblies
// use this if the type isn't loaded in this AppDomain yet.
//Assembly asm = Assembly.LoadFile("path to assembly here", new Evidence());
String typeToLoad = "Master.Enterprise"; // this can be from a config or database call
Type objType = asm.GetType(typeToLoad, true);
if (!objType.IsPublic)
return null;
// make sure the type isn't Abstract
if (((objType.Attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract))
return null;
// IEnterprise is the interface that all of the plugin types must implement to be loaded
Type objInterface = objType.GetInterface("IEnterprise", true);
if (objInterface == null)
return null;
var iri = (IEnterprise)Activator.CreateInstance(objType);
return iri;
精彩评论