gpt4 book ai didi

c# - 反射.emit System.InvalidProgramException : Common Language Runtime detected an invalid program

转载 作者:太空狗 更新时间:2023-10-29 23:32:10 26 4
gpt4 key购买 nike

我是 reflection.emit 的新手,一直在尝试生成以下 C# 代码:

public class RepositoryWrapper
{
public void CallRepositoryMethod(IAddressRepository repository, Address address)
{
repository.NODE_I_NodeExtendedDetails_Address3(address.NodeId);
}
}

这是它的 il 表示:

    IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: callvirt instance int32 ReflectionServices.Node::get_NodeId()
IL_0008: callvirt instance void ReflectionServices.IAddressRepository::NODE_I_NodeExtendedDetails_Address3(int32)
IL_000d: nop
IL_000e: ret

这是我用来创建它的代码:

 internal static void Generate(this System.Reflection.Emit.ILGenerator @this, Type target,string method,Type instance)
{

var methodToCall = target.GetMethod(method);
var methodParams = methodToCall.GetParameters();
var instanceProperties = instance.GetProperties(BindingFlags.Public | BindingFlags.Instance);

var orderedProperties = (from mp in methodParams
join p in instanceProperties
on mp.Name.ToLower() equals p.Name.ToLower()
select p).ToArray();

//add properties to the string builder

//load the object reference onto the stack sothat we can access its methods
@this.Emit(OpCodes.Nop);
@this.Emit(OpCodes.Ldarg_1);
@this.Emit(OpCodes.Ldarg_2);

var property = orderedProperties.FirstOrDefault(x => x.Name == "NodeId");
if (property != null)
{
var getMethod = property.GetGetMethod();
@this.Emit(getMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, getMethod);

}


//call method
@this.Emit(methodToCall.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, methodToCall);
@this.Emit(OpCodes.Nop);
//return from function
@this.Emit(OpCodes.Ret);
}

这是我遇到的错误:

System.InvalidProgramException: Common Language Runtime detected an invalid program.
Result StackTrace:
at ReflectionServices.Repository.NODE_I_NodeExtendedDetails3_Address40807399(Repository target, Address )

这是生成的 il:

nop
ldarg.1
ldarg.2
call instance int32 ReflectionServices.Node::get_NodeId()
callvirt instance void
ReflectionServices.Repository::
NODE_I_NodeExtendedDetails3_Address(int32)
nop

返回

谁能看出我卡住了是什么问题?

谢谢

这是我要求的dll和方法:

 public sealed class ReflectionEmitWithDebuggingMethodGenerator
{
private AssemblyBuilder Assembly { get; set; }
private ModuleBuilder Module { get; set; }
private AssemblyName Name { get; set; }

public ReflectionEmitWithDebuggingMethodGenerator()
: base()
{
this.Name = new AssemblyName() { Name = Guid.NewGuid().ToString("N") };
this.Assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
this.Name, AssemblyBuilderAccess.RunAndSave,@"C:\Users\darren\Documents\Visual Studio 2012\Projects\UnityInjection");
this.AddDebuggingAttribute(this.Assembly);
this.Module = this.Assembly.DefineDynamicModule(this.Name.Name + ".dll", true);
}
public Action<TObject, TInstance> Generate<TObject, TInstance>(Type target, string methodN, Type instanceType)
{
var type = this.Module.DefineType(target.Namespace + "." + target.Name);
var methodName = methodN + target.GetHashCode().ToString();
var method = type.DefineMethod(methodName, MethodAttributes.Static | MethodAttributes.Public, typeof(void), new Type[] { target, instanceType });
method.DefineParameter(1, ParameterAttributes.In, "target");
method.DefineParameter(2, ParameterAttributes.In, "instance");

ILGenerator.Generate(method.GetILGenerator(), target,methodN,instanceType);

var createdType = type.CreateType();

var createdMethod = createdType.GetMethod(methodName);
return (Action<TObject, TInstance>)Delegate.CreateDelegate(typeof(Action<TObject, TInstance>), createdMethod);
}


}

最佳答案

比较编译和发出的输出,只有一个区别:

编译:

callvirt instance int32 ReflectionServices.Node::get_NodeId()

发出:

call instance int32 ReflectionServices.Node::get_NodeId()

您调用 int32 get_NodeId() 的类型是 ReflectionServices.Node,但是您传递给您尝试的方法的对象类型要复制的是 Address。这使我相信必须以虚拟方式调用定义在 ReflectionServices.Node 上的属性访问器,可能是因为它继承自另一个在 ReflectionServices.Node 之前声明该属性的类(或实现接口(interface)) 实现它。

当您发出该行代码时,只需虚拟地调用它:

@this.Emit(OpCodes.Callvirt, getMethod);

编辑:根据进一步提供的代码,这是真正的解决方案。

因此,您在实现接口(interface)的基础知识方面遇到了问题:

var method = type.DefineMethod(methodName, MethodAttributes.Static | Method...
// ^^^^^^

接口(interface)方法不是静态的;他们是实例成员。因此,您首先需要在创建 MethodBuilder 时从属性标志中删除 MethodAttributes.Static

其次,当您返回此函数时,您将必须包含一个目标对象,它是调用该方法的实例。为此,您可以使用 Activator.CreateInstance调用默认生成的构造函数并为您提供一个实例化对象以用作目标。用这些行替换 Generate 方法的最后一行以实现这一点。

var activatedObject = Activator.CreateInstance(type);

return (Action<TObject, TInstance>)Delegate.CreateDelegate(
typeof(Action<TObject, TInstance>), activatedObject, createdMethod);

关于c# - 反射.emit System.InvalidProgramException : Common Language Runtime detected an invalid program,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16950272/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com