3

我已经阅读了其他一些答案以进行动态转换,但我不确定它们是否解决了我想要解决的问题,因此是这个问题。

我有一个界面

public interface ICustomTransmitter<T> : IDataTransmitter where T : EventArgs
{
    event EventHandler<T> DataEvent;
}

以及一组允许我在运行时获取泛型类型参数的函数。这是为了转换为该类型并连接特定事件(这是思想代码,所以请温柔)

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;
}

以及使用上述魔法的功能

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 
}

是否可以将接收器转换为创建的类型?此外,我需要有一个适用于 dot net 3.5 和 dot net 4 的解决方案。

4

2 回答 2

2

没有任何类型的铸造可以做到这一点。强制转换是关于检查运行时类型是否是已知的编译时类型。你甚至没有编译时类型。

您需要做的是使用反射来查找接口,提取泛型类型参数,创建兼容的委托,并为委托连接处理程序。您已经完成了IsOfType.

当你连接一个事件处理程序时,你正在调用它的add方法。编译器为此方法生成一个名称,其格式为“add_EventName”。这是一些可以完成所有这些工作的示例代码:

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());
    }
}
于 2013-08-24T08:15:36.487 回答
1

不可以。您不能将表达式转换为编译时未知的类型。(通过“已知”,我的意思是可解析Type为其泛型类型参数已关闭。)

话虽如此,我认为使用表达式 API 可能是可能的。这个想法是,您将构建您确定的类型(可以是强类型)的 lambda 表达式,编译它,然后在您的对象上执行它以执行强制转换。如果你 100% 需要这样做,这就是我要寻找的方向。

于 2013-08-24T07:22:08.443 回答