Reputation: 571
I am trying to dynamically call an explicitly implemented method using reflection. My method is as follows:
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;
}
I call this method as follows:
// ... calculate and set the slow moving average value
var slowArguments = new object[] { SlowPeriod, CurrentBar, Input, slowAverage};
movingAvg = GetValueOfAverage("MovingAverage", slowAvgMethod, slowArguments);
And my moving average class is implemented as follows:
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;
}
}
I get the following error:
Could not load type 'MovingAverage' from assembly 'f9e1d550bd4d44ddbdc78abaffa07d31, Version=7.0.1000.22, Culture=neutral, PublicKeyToken=null'.
I have tried adding the namespace to the class specification but that did not work either. What I did is as follows:
In the GetValueOfAverage method, I inserted the following code
var methodInfo = System.Reflection.MethodBase.GetCurrentMethod();
var fullName = methodInfo.DeclaringType.FullName + "." + methodInfo.Name;
string str = methodInfo.DeclaringType.FullName + ".";
before the line
Type calledType = Type.GetType(typeName, true);
and replaced the line
Type calledType = Type.GetType(typeName, true);
with
Type calledType = Type.GetType(str+typeName, true);
Can someone please help me understand what I am doing wrong? Any suggestions and/or advice would be greatly appreciated. Thank you.
Upvotes: 2
Views: 211
Reputation: 256
For code loading class, please try to specify namespace like in example below:
movingAvg = GetValueOfAverage("ConsoleApplication1.MovingAverage", slowAvgMethod, slowArguments);
It may be still not enough if type is located in assembly that is currently not loaded yet. In this situation you may need to specify type with assembly qualified name like below:
movingAvg = GetValueOfAverage("ConsoleApplication1.MovingAverage, ConsoleApplication1", slowAvgMethod, slowArguments);
(where first ConsoleApplication1. is namespace, and second ConsoleApplication1 is assembly name)
Finally, you have a mistake in code calling method via reflection, where arguments are passed as nested object[] array. Arguments parameter is already passed as object[] so it should be passed directly to InvokeMember() method:
double avg = (double)calledType.InvokeMember(
methodName,
BindingFlags.InvokeMethod | BindingFlags.Public |
BindingFlags.Static | BindingFlags.NonPublic,
null,
null,
arguments);
I have updated this post with full example to visualize how to pass type. The code below is compiled to 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;
}
}
}
Upvotes: 1
Reputation: 3150
You need to fully qualify the MovingAverage type
Type.GetType("MovingAverage");
won't work unless you have overridden the TypeResolve event.
You need to use
Type.GetType("MovingAverageNamespace.MovingAverage, MovingAverageDllWithoutExtension");
Upvotes: 0