C#:使用反射动态调用显式实现的方法

C#:使用反射动态调用显式实现的方法,c#,reflection,invoke,C#,Reflection,Invoke,我尝试使用反射动态调用显式实现的方法。我的方法如下: public static double GetValueOfAverage(string typeName, string methodName, object[] arguments){ // ... get the Type for the class Type calledType = Type.GetType(typeName, true); double avg = (double)calledType

我尝试使用反射动态调用显式实现的方法。我的方法如下:

public static double GetValueOfAverage(string typeName, string methodName, object[] arguments){
    // ... get the Type for the class
    Type calledType = Type.GetType(typeName, true);

    double avg  = (double)calledType.InvokeMember(
        methodName,
        BindingFlags.InvokeMethod | BindingFlags.Public | 
        BindingFlags.Static | BindingFlags.NonPublic,
        null,
        null,
        new object[] { arguments }
    );

    // Return the value returned by the called method.
    return avg;
}
// ... calculate and set the slow moving average value
var slowArguments = new object[] { SlowPeriod, CurrentBar, Input, slowAverage};
movingAvg = GetValueOfAverage("MovingAverage", slowAvgMethod, slowArguments);
public static class MovingAverage{
    public static double _EMA(int Period, int CurrentBar, DataSeries Input, DataSeries average){
        double avg = CurrentBar == 0 ? Input[0] : Input[0] * (2.0 / (1 + Period)) + (1 - (2.0 / (1 + Period))) * average[1];
        return avg;
    }
}
我将此方法称为:

public static double GetValueOfAverage(string typeName, string methodName, object[] arguments){
    // ... get the Type for the class
    Type calledType = Type.GetType(typeName, true);

    double avg  = (double)calledType.InvokeMember(
        methodName,
        BindingFlags.InvokeMethod | BindingFlags.Public | 
        BindingFlags.Static | BindingFlags.NonPublic,
        null,
        null,
        new object[] { arguments }
    );

    // Return the value returned by the called method.
    return avg;
}
// ... calculate and set the slow moving average value
var slowArguments = new object[] { SlowPeriod, CurrentBar, Input, slowAverage};
movingAvg = GetValueOfAverage("MovingAverage", slowAvgMethod, slowArguments);
public static class MovingAverage{
    public static double _EMA(int Period, int CurrentBar, DataSeries Input, DataSeries average){
        double avg = CurrentBar == 0 ? Input[0] : Input[0] * (2.0 / (1 + Period)) + (1 - (2.0 / (1 + Period))) * average[1];
        return avg;
    }
}
我的移动平均线课程实施如下:

public static double GetValueOfAverage(string typeName, string methodName, object[] arguments){
    // ... get the Type for the class
    Type calledType = Type.GetType(typeName, true);

    double avg  = (double)calledType.InvokeMember(
        methodName,
        BindingFlags.InvokeMethod | BindingFlags.Public | 
        BindingFlags.Static | BindingFlags.NonPublic,
        null,
        null,
        new object[] { arguments }
    );

    // Return the value returned by the called method.
    return avg;
}
// ... calculate and set the slow moving average value
var slowArguments = new object[] { SlowPeriod, CurrentBar, Input, slowAverage};
movingAvg = GetValueOfAverage("MovingAverage", slowAvgMethod, slowArguments);
public static class MovingAverage{
    public static double _EMA(int Period, int CurrentBar, DataSeries Input, DataSeries average){
        double avg = CurrentBar == 0 ? Input[0] : Input[0] * (2.0 / (1 + Period)) + (1 - (2.0 / (1 + Period))) * average[1];
        return avg;
    }
}
我得到以下错误:

无法从程序集“F9E1D550BD4D44DDBDC78ABAFA07D31,版本=7.0.1000.22,区域性=中性,PublicKeyToken=null”加载类型“MovingAverage”

我曾尝试将名称空间添加到类规范中,但也没有成功。我所做的如下:

public static double GetValueOfAverage(string typeName, string methodName, object[] arguments){
    // ... get the Type for the class
    Type calledType = Type.GetType(typeName, true);

    double avg  = (double)calledType.InvokeMember(
        methodName,
        BindingFlags.InvokeMethod | BindingFlags.Public | 
        BindingFlags.Static | BindingFlags.NonPublic,
        null,
        null,
        new object[] { arguments }
    );

    // Return the value returned by the called method.
    return avg;
}
// ... calculate and set the slow moving average value
var slowArguments = new object[] { SlowPeriod, CurrentBar, Input, slowAverage};
movingAvg = GetValueOfAverage("MovingAverage", slowAvgMethod, slowArguments);
public static class MovingAverage{
    public static double _EMA(int Period, int CurrentBar, DataSeries Input, DataSeries average){
        double avg = CurrentBar == 0 ? Input[0] : Input[0] * (2.0 / (1 + Period)) + (1 - (2.0 / (1 + Period))) * average[1];
        return avg;
    }
}
在GetValueOfAverage方法中,我插入了以下代码

var methodInfo = System.Reflection.MethodBase.GetCurrentMethod();
var fullName = methodInfo.DeclaringType.FullName + "." + methodInfo.Name;
string str = methodInfo.DeclaringType.FullName + ".";
排队前

Type calledType = Type.GetType(typeName, true);
并更换了线路

Type calledType = Type.GetType(typeName, true);


有人能帮我理解我做错了什么吗?如有任何建议和/或建议,将不胜感激。谢谢。

您需要完全限定移动平均值类型

Type.GetType("MovingAverage");
除非已重写TypeResolve事件,否则将无法工作

你需要使用

Type.GetType("MovingAverageNamespace.MovingAverage, MovingAverageDllWithoutExtension");

对于代码加载类,请尝试指定命名空间,如下例所示:

movingAvg = GetValueOfAverage("ConsoleApplication1.MovingAverage", slowAvgMethod, slowArguments);
如果类型位于当前尚未加载的程序集中,则可能仍然不够。 在这种情况下,可能需要使用程序集限定名指定类型,如下所示:

movingAvg = GetValueOfAverage("ConsoleApplication1.MovingAverage, ConsoleApplication1", slowAvgMethod, slowArguments);
(其中第一个ConsoleApplication1.是命名空间,第二个ConsoleApplication1是程序集名称)

最后,在通过反射调用方法的代码中有一个错误,其中参数作为嵌套对象[]数组传递参数参数已作为对象[]传递,因此应直接传递给InvokeMember()方法:

我已经用完整的例子更新了这篇文章,以可视化如何传递类型。 下面的代码编译为ConsoleApplication1.exe

using System;
using System.Reflection;

namespace MyNamespace
{
    public static class MovingAverage
    {
        public static double MyMethod(int Period, int CurrentBar, int[] Input, int[] average)
        {
            return 5;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var arguments = new object[] { 1, 2, new[] { 2 }, new[] { 4 } };

            Console.WriteLine(GetValueOfAverage("MyNamespace.MovingAverage", "MyMethod", arguments)); //if assembly is already loaded
            Console.WriteLine(GetValueOfAverage("MyNamespace.MovingAverage, ConsoleApplication1", "MyMethod", arguments)); //if assembly is not loaded yet
            Console.WriteLine(GetValueOfAverage(typeof(MovingAverage), "MyMethod", arguments)); //known type
            Console.ReadKey();
        }

        public static double GetValueOfAverage(string typeName, string methodName, object[] arguments)
        {
            // ... get the Type for the class
            Type calledType = Type.GetType(typeName, true);
            return GetValueOfAverage(calledType, methodName, arguments);
        }

        public static double GetValueOfAverage(Type calledType, string methodName, object[] arguments)
        {
            double avg = (double)calledType.InvokeMember(
                           methodName,
                           BindingFlags.InvokeMethod | BindingFlags.Public |
                           BindingFlags.Static | BindingFlags.NonPublic,
                           null,
                           null,
                           arguments);

            // Return the value returned by the called method.
            return avg;
        }
    }
}

该类在调用程序集中吗?@wbennett:是的。需要完整的命名空间。添加时,您是否100%
fullName
的值具有正确的名称空间?@mximmit:Yes。我再试了一次,并明确地在名称空间中键入了内容(并检查键入的内容是否正确)。谢谢您的建议。很抱歉我不理解MovingAverage,但MovingAverage是一个已实现的类,所以为什么我需要使用MovingAveragedLWithoutExtension?我尝试了你的建议,但它冻结了程序。我不知道我做错了什么。谢谢你的建议。我没有发现这些参数的错误。谢谢你指出这一点。如何获取用作第二个控制台应用程序1的程序集的名称?它通常是MovingAverage源文件所在的项目的名称。如果将代码编译为可执行文件或dll,则程序集名称通常是不带扩展名的dll/exe名称。当然,它可以在VisualStudio中进行自定义:您必须转到项目的属性,并且在“应用程序”选项卡中会出现“程序集名称”字段。有没有办法通过代码获取此字段?这是调用程序集还是执行程序集?我不完全明白你的问题。您可以始终执行typeof(MovingAverage)并将其传递给GetValueOfAverage()而不是typeName,这样就不再需要Type.GetType()。但是,如果你确切知道它的类型,那么使用反射来调用它有什么意义:)我已经尝试过了,但没有成功。我会再试一次。非常感谢。