Cast to a reflected Type in C#
No :-)
Case 1:
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Foo result = (Foo)objFoo;
There is no reflection here, because you know the Foo
type at compile time.
Case 2: interfaces. Normally the best one... You don't know what exactly MakeFoo
returns, but you know it's an IFoo
interface...
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
IFoo result = (IFoo)objFoo;
Case 3: you aren't sure MakeFoo
returns Foo
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
if (objFoo is Foo)
{
Foo result = (Foo)objFoo;
}
or, similar
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Foo foo = objFoo as Foo;
if (foo != null)
{
// use foo
}
Case 4: type Foo
is completely unknown to your program. You don't have a Foo
class referenceable...
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Type typeFoo = objFoo.GetType(); // You should check for null values before!
// and now?
dynamic foo = objFoo;
// because you know that foo can Quack(1, 2, 3)!
string result = foo.Quack(1, 2, 3);
// note that it will explode with a RuntimeBinderException if there is no
// string Quack(int, int, int) method!
the dynamic
internally uses reflection. You could use reflection directly to get the Quack
method and call it
Case 5: as case 4, but using directly reflection:
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Type typeFoo = objFoo.GetType(); // You should check for null values before!
MethodInfo mi = type.GetMethod("Quack"); // You should check if the Quack method
// exists
string result = (string)mi.Invoke(objFoo, new object[] { 1, 2, 3 });
or, with some sanity checks, if you aren't sure foo
can Quack
correctly:
MethodInfo mi = type.GetMethod("Quack",
BindingFlags.Instance | BindingFlags.Public,
null,
new[] { typeof(int), typeof(int), typeof(int) },
null);
if (mi != null && typeof(string).IsAssignableFrom(mi.ReturnType))
{
string result = (string)mi.Invoke(objFoo, new object[] { 1, 2, 3 });
}
Case -Infinity: type Foo
is completely unknown to your program. You don't have a Foo
class referenceable. You don't have an IFoo
interface. You don't even know what a Foo
is, you know only that it's a class (or perhaps it's a boxed struct
, but it doesn't change from your point of view... It can't be an interface
because in the end there must always be a concrete class
/struct
behind every interface
). You don't know of its methods, its fields, its properties (because you don't know what Foo
is).
Even if you can cast an object
to this unknown class, what can you do? You can't have methods in your code that accept it as a parameter/return value, because if somewhere you had:
int INeedFoo(Foo par) { return 0; }
then clearly you would know of Foo
. The .NET library can't have methods that accept it as a parameter/return value, because if it had, you would know of Foo
.
The only thing you can do is pass it to some other methods that you discover through reflection that accept Foo
as a parameter... But the Invoke
method accepts an array of object
as parameters... You don't need to cast your object
to call Invoke
! You only need to put it in the array.
This is the first result in google about Casting to a reflected type.
So for reference, in case sb wonders what would be a general way of casting to a reflected type:
public static class ObjectExtensions
{
public static T CastTo<T>(this object o) => (T)o;
public static dynamic CastToReflected(this object o, Type type)
{
var methodInfo = typeof(ObjectExtensions).GetMethod(nameof(CastTo), BindingFlags.Static | BindingFlags.Public);
var genericArguments = new[] { type };
var genericMethodInfo = methodInfo?.MakeGenericMethod(genericArguments);
return genericMethodInfo?.Invoke(null, new[] { o });
}
}