I have read through some of the other answers to do a dynamic cast and I am not sure they address the situation I want to solve hence the question.
I have an interface
public interface ICustomTransmitter<T> : IDataTransmitter where T : EventArgs
{
event EventHandler<T> DataEvent;
}
and a set of functions that allow me to get the generic type argument at runtime. This is in order to cast to that type and hook up the specific event (this is thought code so please be gentle)
public bool IsTypeOf(Type baseType, Type interfaceType,
out Type argumenType)
{
var interfaces = baseType.GetInterfaces();
argumenType = null;
foreach (Type @interface in interfaces)
{
if (@interface.Name != interfaceType.Name) continue;
if (@interface.IsGenericType)
{
argumenType = @interface.GetGenericArguments()[0];
}
return true;
}
return false;
}
And the function that uses the magic above
Type argument;
var generic = typeof (ICustomTransmitter<>);
if (IsTypeOf(receiver.GetType(),generic ,out argument))
{
var created = generic.MakeGenericType(new[] {argument});
//the line of code missing is below
receiver as created
}
Is it possible to cast the receiver to that created type? Also I need to have a solution that works in both dot net 3.5 and dot net 4.
There is no kind of casting that will do that. Casting is about checking if a runtime type is a known compile time type. You don't even have a compile time type.
What you need to do is use reflection to look for the interface, extract the generic type argument, create a compatible delegate, and hook up the handler for the delegate. You've got the first couple steps with IsOfType.
When you hook up an event handler you are calling its add method. The compiler generates a name for this method that is of the form "add_EventName". Here is some sample code that does all that stuff:
using System;
using System.Reflection;
public class Program
{
public static void Main(string[] args)
{
object o = new CustomArgsTransmitter();
// make sure we've got the interface
var interf = o.GetType().GetInterface("ICustomTransmitter`1");
// get the arg type.
var argType = interf.GetGenericArguments()[0];
// create a delegate for the handler based on the arg type above
var handlerMethodInfo = typeof(Program).GetMethod("Handler", BindingFlags.Static | BindingFlags.Public)
var del = Delegate.CreateDelegate(typeof(EventHandler<>).MakeGenericType(argType), handlerMethodInfo);
// Invoke the add method of the event.
o.GetType().InvokeMember("add_DataEvent", BindingFlags.InvokeMethod, null, o, new object[] { del });
// just test code at this point.
// fire event to make sure it is signed up.
// It should print a message to the console.
((CustomArgsTransmitter)o).FireEvent();
}
public static void Handler(object sender, EventArgs e)
{
Console.WriteLine("Got event {0} from {1}", e, sender);
}
}
public interface IDataTransmitter { }
public interface ICustomTransmitter<T> : IDataTransmitter where T : EventArgs
{
event EventHandler<T> DataEvent;
}
public class MyArgs : EventArgs { }
public class CustomArgsTransmitter : ICustomTransmitter<MyArgs>
{
public event EventHandler<MyArgs> DataEvent;
public void FireEvent()
{
DataEvent(this, new MyArgs());
}
}
No. You cannot cast an expression to a type that is not known at compile time. (By "known", I mean resolvable to a Type whose generic type parameters are closed.)
Having said that, I think it may be possible by using the expression API. The idea is that you would build a lambda expression of the type you determined (which can be strongly-typed), compile it, then execute it on your object to perform the cast. If you 100% need to do this, that's the direction I'd look.
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