I want to create dynamic function in my project, but the number of function parameters is not sure,maybe two,maybe three or more,and then i want to run a static function already in the project,the static function accept some parameters,so,how could i do it with emit? and the most important is how to deal the parameters?
My dynamic function demo
public static void UDFCreate(string name, string type,List<string> paramList, string APIID)
{
Type[] types = new Type[paramList.Count];
foreach (string param in paramList)
{
int index = paramList.IndexOf(param);
types[index] = typeof(double);
}
DynamicMethod mult = new DynamicMethod(name, typeof(double), types, typeof(UDFGenerator));
ILGenerator il = mult.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);//
il.Emit(OpCodes.Ldarg_1);//
il.Emit(OpCodes.Add);//
il.Emit(OpCodes.Ret);//
List<Delegate> delegates = new List<Delegate>();
delegates.Add(mult.CreateDelegate(typeof(Func<double, double, double>)));
//
ExcelFunctionAttribute att = new ExcelFunctionAttribute();
att.Name = name;
att.Description = "A function to multiply two numbers";
List<object> funcAttribs = new List<object>();
funcAttribs.Add(att);
//
ExcelArgumentAttribute atta1 = new ExcelArgumentAttribute();
atta1.Description = "is the first number";
ExcelArgumentAttribute atta2 = new ExcelArgumentAttribute();
atta2.Description = "is the second number";
List<object> argAttribs = new List<object>();
argAttribs.Add(atta1);
argAttribs.Add(atta2);
List<List<object>> argAttribsList = new List<List<object>>();
argAttribsList.Add(argAttribs);
try
{
//
ExcelIntegration.RegisterDelegates(delegates, funcAttribs, argAttribsList);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
My static function struct, only the paramList need create in runtime,others can get byUDFCreate
private static async void GetApiResult(string id, string type, List<string> paramNameList, params string[] paramList)
After two days later Thanks @JeremyLakeman very much,that really helpful.And then I coding like this
private static void EmitTwo(ILGenerator il, string type, List<string> paramList, string APIID)
{
// Stores the APIID in a local variable with index 0
il.Emit(OpCodes.Ldarg_0); // this line is must
il.Emit(OpCodes.Ldfld, APIID);
il.Emit(OpCodes.Stloc_0);
// Stores the type in a local variable with index 1
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, type);
il.Emit(OpCodes.Stloc_1);
// Create an array of the same size as the paramList
il.Emit(OpCodes.Ldc_I4, paramList.Count);
il.Emit(OpCodes.Newarr, typeof(object));
foreach (var param in paramList)
{
int index = paramList.IndexOf(param);
// Replaces the value of the array with an input parameter, subscript should starts at 1
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldc_I4, index);
il.Emit(OpCodes.Ldarg_S, index + 1);
il.Emit(OpCodes.Stelem_Ref);
}
il.Emit(OpCodes.Stloc_2);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Call, "GetApiResult");
il.Emit(OpCodes.Ldstr, "LOADING");
il.Emit(OpCodes.Ret);
}
But it cant work fine,i got the errors in il.Emit(OpCodes.Ldfld, APIID);
and in il.Emit(OpCodes.Call, "GetApiResult");
.I have tried, but i dont known how to deal that,could you help to fix that?
My goal is seems like thissample
Simplifying your example (from comments), you want to generate a method like;
Which would result in IL similar to;
I don't have any actual experience with using
il.Emit
, but I would suggest you start by trying to output that method exactly. Then turn the array creation into a loop. Modifying the lines above which have comments, into the similarldc.i4
/ldarg
op codes which allow you to specify an explicitint
or argument value.