如何在C#EMIT中使用不确定参数创建动态函数
我想在项目中创建动态函数,但是函数参数的数量不确定,也许是两个,也许是三个或更多,然后我想在项目中运行静态函数,静态函数接受某些参数,因此,我该怎么做?最重要的是如何处理参数?
我的动态函数演示
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);
}
我的静态函数结构,只有 paramlist 需要在运行时创建,其他人可以
private static async void GetApiResult(string id, string type, List<string> paramNameList, params string[] paramList)
在两天后 通过 udfcreate 获得 非常感谢@jeremylakeman,非常有帮助
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);
}
。 il.emit(opcodes.call,“ getapiresult”); 。我已经尝试过,但是我不知道该如何处理,您能帮上解决这个问题吗? My goal is seems like thissample
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
简化了您的示例(从注释),您想生成类似的方法;
Which would result in IL similar to;
我没有使用
il.emit
的实际经验,但是我建议您首先尝试准确输出该方法。然后将数组创建变成循环。修改上面具有注释的行,以相似的ldc.i4
/ldarg
op代码,允许您指定显式int
或参数值值。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.