首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模拟.NET 3.5委托中的变化

模拟.NET 3.5委托中的变化
EN

Stack Overflow用户
提问于 2010-10-13 12:03:45
回答 1查看 303关注 0票数 2

我有一个方法,给定一个委托Type参数(而不是泛型),它返回它创建的实现签名的Delegate。它在内部使用表达式树创建了一个动态方法。委托类型必须是这种形式的Func<SomeParam,IamDerivedObject>,一个函数,其中IamDerivedObject是IamDerivedObject的继承者。该方法使用类型信息来确定要实例化的对象,因此简单地使用接口进行创建将是灾难性的。调用是从一个返回IamDerivedObject的静态方法完成的。

在.NET 4代码中,我可以这样做::var myDelegate = MakeMethod(typeArgument) as Func<SomeParam,IamDerivedObject>

在.Net 3.5中,这不起作用。我不得不知道调用invoke方法的类型,或者使用另一个表达式生成的委托来调用它并缓存该委托。这意味着更多的运行时生成的代码。不幸的是,我暂时不能使用.NET 4代码,因为程序集必须是.NET 3.5代码,因为它依赖于一个不能在4.0中工作的第三方dll。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-10-23 03:23:22

我想出了一种方法,但它基本上需要一些反射魔法才能弄清楚。

代码语言:javascript
复制
    /// <summary>
    /// Converts the delegate to <see cref="TDelegate"/>, provided the types are compatible. Can use
    /// variance of delegate typing in .NET 4 for a speedy conversion. Otherwise, uses Delegate.CreateDelegate
    /// to create a new delegate with the appropriate signature. 
    /// </summary>
    /// <typeparam name="TDelegate">The target delegate type.</typeparam>
    /// <param name="delegate">The @delegate.</param>
    /// <returns></returns>
    public static TDelegate ConvertDelegate<TDelegate>(Delegate @delegate) where TDelegate : class
    {
        ArgumentValidator.AssertIsNotNull(() => @delegate);
        var targetType = typeof(TDelegate);
        ArgumentValidator.AssertIsDelegateType(() => targetType);
        var currentType = @delegate.GetType();
        if (targetType.IsAssignableFrom(currentType))
        {
            return @delegate as TDelegate; // let's skip as much of this as we can.
        }

        var currentMethod = currentType.GetMethod("Invoke");
        var targetMethod = targetType.GetMethod("Invoke");
        if (!AreDelegateInvokeMethodsCompatible(currentMethod, targetMethod, true))
        {
            throw new ArgumentException(string.Format("{0} is incompatible with {1}.", currentType, targetType), ExpressionHelper.GetMemberName(() => @delegate));
        }
        var invocationList = @delegate.GetInvocationList();
        return DelegateHelper.Combine(@delegate.GetInvocationList()
            .Select(d => IsMethodRunTimeGenerated(d.Method) ?
                        GetDynamicMethodFromMethodInfo(d.Method).CreateDelegate<TDelegate>(d.Target) :
                        DelegateHelper.CreateDelegate<TDelegate>(d.Target, d.Method)).ToArray());
    }
    #region Private Static Variables 
    private static Type s_RTDynamicMethodType = Type.GetType("System.Reflection.Emit.DynamicMethod+RTDynamicMethod",false,true);
    private static Func<MethodInfo, DynamicMethod> s_GetDynamicMethodDelegate = CreateGetDynamicMethodDelegate();
    #endregion Private Static Variables 

    private static Func<MethodInfo, DynamicMethod> CreateGetDynamicMethodDelegate()
    {
        var param = Expression.Parameter(
                        typeof(MethodInfo),
                        typeof(MethodInfo).Name
        );
        var expression = Expression.Lambda<Func<MethodInfo, DynamicMethod>>(
            Expression.Field(
                Expression.Convert(
                    param,
                    s_RTDynamicMethodType
                ),
                s_RTDynamicMethodType.GetField("m_owner", BindingFlags.NonPublic | BindingFlags.Instance)
            ),
            param
            );
        return expression.Compile();
    }

我不会放弃我的delegatehelper类,除非其他人真的想要它。但重点是这是可能的,而且实际上是相当快的。转换通常不到1ms,没有接近瞬时的方法组转换快,但你知道这是有意义的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3920684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档