c# – Reflection.Emit使用参数创建对象
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – Reflection.Emit使用参数创建对象,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3862字,纯文字阅读大概需要6分钟。
内容图文
![c# – Reflection.Emit使用参数创建对象](/upload/InfoBanner/zyjiaocheng/799/7a32968a23024792bc5c449a819f6412.jpg)
我正在创建一个动态函数,在给定构造函数params的object []的情况下在运行时创建一个对象.我一直得到通用异常’操作可能会破坏运行时’,我看不出我做错了什么.
如果创建的对象不需要构造函数参数,则该方法可以正常工作 – 因此问题必须在for循环中的代码中.
代码索引到给定的对象[]中,将对象放入堆栈,然后调用ctor并返回对象.
有任何想法吗???
internal static Func<object[], object> CreateObjectFactoryMethodWithCtorParams(ConstructorInfo ctor, int ctorArgsLength)
{
Func<object[], object> factoryMethod = null;
if (ctor != null)
{
var dm = new DynamicMethod(string.Format("_CreationFacotry_{0}", Guid.NewGuid()), typeof(object), new Type[] { typeof(object[])}, true);
var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int));
il.DeclareLocal(typeof(object));
il.BeginExceptionBlock();
il.Emit(OpCodes.Ldc_I4_0); // [0]
il.Emit(OpCodes.Stloc_0); //[nothing]
for (int i = 0; i < ctorArgsLength; i++)
{
EmitInt32(il, i); // [args][index]
il.Emit(OpCodes.Stloc_0); // [args][index]
il.Emit(OpCodes.Ldarg_0); //[args]
EmitInt32(il, i); // [args][index]
il.Emit(OpCodes.Ldelem_Ref); // [item-in-args-at-index]
}
il.Emit(OpCodes.Newobj, ctor); //[new-object]
il.Emit(OpCodes.Stloc_1); // nothing
il.BeginCatchBlock(ExceptionType); // stack is Exception
il.Emit(OpCodes.Ldloc_0); // stack is Exception, index
il.EmitCall(OpCodes.Call, EmitGeneratorType.GetMethod("ThrowFactoryException"), null);
il.EndExceptionBlock();
il.Emit(OpCodes.Ldloc_1); //[new-object]
il.Emit(OpCodes.Ret);
factoryMethod = (Func<object[], object>)dm.CreateDelegate(typeof(Func<object[], object>));
}
else
{
throw new EmitGeneratorException("Cannot create instance factory for a null ctor instance");
}
return factoryMethod;
}
private static void EmitInt32(ILGenerator il, int value)
{
switch (value)
{
case -1: il.Emit(OpCodes.Ldc_I4_M1); break;
case 0: il.Emit(OpCodes.Ldc_I4_0); break;
case 1: il.Emit(OpCodes.Ldc_I4_1); break;
case 2: il.Emit(OpCodes.Ldc_I4_2); break;
case 3: il.Emit(OpCodes.Ldc_I4_3); break;
case 4: il.Emit(OpCodes.Ldc_I4_4); break;
case 5: il.Emit(OpCodes.Ldc_I4_5); break;
case 6: il.Emit(OpCodes.Ldc_I4_6); break;
case 7: il.Emit(OpCodes.Ldc_I4_7); break;
case 8: il.Emit(OpCodes.Ldc_I4_8); break;
default:
if (value >= -128 && value <= 127)
{
il.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
}
else
{
il.Emit(OpCodes.Ldc_I4, value);
}
break;
}
}
调用代码
Func<object[], object> factoryFunction = GetFunction(someCtor, new object[] { arg1, arg2});
var obj = factoryFunction(new object[] {new SomeClass, "A String" }); //input ctor args
解决方法:
它对我来说很好,只要我创建所有构造函数参数对象:
class SomeClass {
public SomeClass(object s, object t) { }
}
static void Main()
{
var someCtor = typeof(SomeClass).GetConstructors()[0];
Func<object[], object> factoryFunction = CreateObjectFactoryMethodWithCtorParams(someCtor, someCtor.GetParameters().Length);
var obj = factoryFunction(new object[] {"A String", 123 });
}
我认为问题是你没有从数组中的对象到实际的构造函数类型进行任何转换,注意到你需要同时考虑引用类型和值类型(unbox).像这样:
var parameters = ctor.GetParameters();
for (int i = 0; i < parameters.Length ; i++)
{
EmitInt32(il, i); // [index]
il.Emit(OpCodes.Stloc_0); // [nothing]
il.Emit(OpCodes.Ldarg_0); //[args]
EmitInt32(il, i); // [args][index]
il.Emit(OpCodes.Ldelem_Ref); // [item-in-args-at-index]
var paramType = parameters[i].ParameterType;
if (paramType != typeof(object))
{
il.Emit(OpCodes.Unbox_Any, paramType); // same as a cast if ref-type
}
}
il.Emit(OpCodes.Newobj, ctor); //[new-object]
il.Emit(OpCodes.Stloc_1); // nothing
作为次要注意事项:既然你需要调用.GetParameters(),你不应该将参数长度作为参数传递给方法;这是多余的,并且可能在错误时导致错误.
这适用于我的exmaple:
class SomeClass {
public SomeClass(string s, int t) { }
}
static void Main()
{
var someCtor = typeof(SomeClass).GetConstructors()[0];
Func<object[], object> factoryFunction = CreateObjectFactoryMethodWithCtorParams(someCtor);
var obj = factoryFunction(new object[] {"A String", 123 });
}
内容总结
以上是互联网集市为您收集整理的c# – Reflection.Emit使用参数创建对象全部内容,希望文章能够帮你解决c# – Reflection.Emit使用参数创建对象所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。