类型'Program + StringEventArgs'的ParameterExpression不能用于类型'System.EventArgs'的委托参数

我正在尝试使用反射将MethodInfo转换为Func<T,TResult>。到目前为止,我的代码在某些情况下似乎可以正常工作,但是我无法创建具有从另一代码派生的参数类型的Func。我缺少了一些东西,但不幸的是,我不知道该如何进行。我想某种Expression.Convert()会井然有序,如果可以,那么在哪里以及如何?

这是一个简短的程序,用于测试我要达到的目标。可以将其复制粘贴到https://dotnetfiddle.net/并进行编译。

using System;
using System.Linq.Expressions;

public class Program
{
    public static void Main()
    {
        var myobject = new MyClass();
        var methodInfo = myobject.GetType().GetMethod("HelloThere");
        var parameterType = methodInfo.GetParameters()[0].ParameterType;
        var parameterExpression = Expression.Parameter(parameterType);
        var callExpression = Expression.Call(Expression.Constant(myobject),methodInfo,parameterExpression);
        var compiledFunction = Expression.Lambda<Func<EventArgs,string>>(callExpression,parameterExpression).Compile();
    }

    public class MyClass
    {
        public string HelloThere(StringEventArgs args)
        {
            return "General Kenobi";
        }
    }

    public class StringEventArgs : EventArgs
    {
        public StringEventArgs(string aString)
        {
            Value = aString;
        }

        public string Value { get; set; }
    }
}

但是,在运行时会引发以下错误:

Run-time exception (line 13): ParameterExpression of type 'Program+StringEventArgs' cannot be used for delegate parameter of type 'System.EventArgs'
Shuzhenabc123 回答:类型'Program + StringEventArgs'的ParameterExpression不能用于类型'System.EventArgs'的委托参数

您的代码有两个问题。

首先,您已声明类型为ParameterExpression的{​​{1}},然后尝试将其用作StringEventArgs中的参数。那行不通:您需要使用Func<EventArgs,string>类型声明ParameterExpression

第二个问题是,您基本上是在尝试使用表达式构造此C#代码:

EventArgs

那不会编译,因为您要使用public string GeneratedMethod(EventArgs e) { return myClass.HelloThere(e); } 类型的对象并将其传递给接受EventArgs的方法。

在C#中,您可以添加强制类型转换,如果您实际上未传递StringEventArgs,则强制类型转换将在运行时失败:

StringEventArgs

等效表达式为public string GeneratedMethod(EventArgs e) { return myClass.HelloThere((StringEventArgs)e); }

将它们放在一起,您将得到:

Expression.Convert

即使您传递的内容不是var myObject = new MyClass(); var methodInfo = myObject.GetType().GetMethod("HelloThere"); var parameterExpression = Expression.Parameter(typeof(EventArgs)); var parameterType = methodInfo.GetParameters()[0].ParameterType; var methodParameter = Expression.Convert(parameterExpression,parameterType); var callExpression = Expression.Call(Expression.Constant(myObject),methodInfo,methodParameter); var compiledFunction = Expression.Lambda<Func<EventArgs,string>>(callExpression,parameterExpression).Compile(); ,尽管运行InvalidCastException也会失败,尽管StringEventArgs的签名表明它可以接受任何类型的compiledFunction

,

使用

调用Lambda方法时
var compiledFunction = Expression.Lambda<Func<EventArgs,parameterExpression).Compile();

您指定的委托类型为Func 。但是,只有当您的参数类型为EventArgs并且HelloType的返回类型为字符串时,情况才会如此。从收到的错误消息中可以看出,这些不是实际的类型。例如,错误是指嵌套在程序类型中的StringEventArgs类型。

此外,如果您知道参数类型为EventArgs,那么动态获取parameterType值将毫无意义。

您可以尝试使用不同的Expression.Lambda重载。忽略类型参数,只需调用

 var compiledFunction = Expression.Lambda(callExpression,new ParameterExpression[] { parameterExpression }).Compile();

这应该从参数表达式的类型和调用表达式的类型动态构造lambda类型。

注意:我实际上没有尝试过。

本文链接:https://www.f2er.com/3097996.html

大家都在问