C# ILGenerated方法中的System.ObjectDisposedException
我添加到生成器字符串中C# ILGenerated方法中的System.ObjectDisposedException,c#,dynamic,reflection,delegates,opcode,C#,Dynamic,Reflection,Delegates,Opcode,我添加到生成器字符串中 ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, readField); 及 转换成基码 private ReadItemDelegate _read; /// <summary> /// Init Get method of instance /// </summary> private void InitGetMethod() {
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, readField);
及
转换成基码
private ReadItemDelegate _read;
/// <summary>
/// Init Get method of instance
/// </summary>
private void InitGetMethod()
{
var ti = typeof (int);
Type[] methodArgs2 = { _globalType, ti, ti, ti, ti, ti, ti, ti, ti, ti, ti };// 10 elements
#region this.Get = double(int, .., int) { return _shift0[i0] + .. + _shiftn[in] }
var dynamicMethod = new DynamicMethod("", ChildrenType, methodArgs2, _globalType);// create dynmic method
var ilGen = dynamicMethod.GetILGenerator();
var fiShift = new FieldInfo[_dims.Length];
for (var i = 0; i < _dims.Length; i++) // get links to all shift arrays
{
fiShift[i] = _globalType.GetField("_shift" + i, BindingFlags.NonPublic | BindingFlags.Instance);
}
var ldargs = new[] {OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3};
var readField = _globalType.GetField("_read", BindingFlags.NonPublic | BindingFlags.Instance);
if (readField == null) throw new ArgumentNullException("_read");
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, readField);
for (var i = 0; i < _dims.Length; i++)
{
ilGen.Emit(OpCodes.Ldarg_0); //push link to class member
ilGen.Emit(OpCodes.Ldfld, fiShift[i]); //push link to shift array
if (i < 3) // push next param
ilGen.Emit(ldargs[i]);
else
ilGen.Emit(OpCodes.Ldarg_S, i+1);
ilGen.Emit(OpCodes.Ldelem_I8); // pop 3 vars and push value from our array by param as index. Result as I8
if (i>0) ilGen.Emit(OpCodes.Add); // pop 2 vars, summ and push back
}
ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());
ilGen.Emit(OpCodes.Ret);
Get = (GetItemDelegate) dynamicMethod.CreateDelegate( typeof(GetItemDelegate), this); // save method as Get variable
#endregion
}
我得到了这个错误,但是当我使用
this._read(2568)
我得到了正确的结果
代码中哪里可能有bug?
任何试图帮助的人都要提前表示感谢。
下面是一个简短的例子来解释错误:
using System;
using System.Collections.Generic;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
public class test
{
public delegate double GetItemDelegate(int i0 = 0, int i1 = 0, int i2 = 0);
public delegate double ReadItemDelegate(Int64 offset);
Type _globalType = typeof(test);
Type ChildrenType = typeof(double);
public GetItemDelegate Get;
private ReadItemDelegate _read;
public test()
{
var file = MemoryMappedFile.CreateOrOpen("file", 123);
var readMethod = typeof(MemoryMappedViewAccessor).GetMethod("ReadDouble");
var viewAccessor = file.CreateViewAccessor(0, 123);
_read = (ReadItemDelegate)Delegate.CreateDelegate(typeof(ReadItemDelegate), viewAccessor, readMethod);
var ti = typeof(int);
Type[] methodArgs2 = { _globalType, ti, ti, ti };// 10 elements
var dynamicMethod = new DynamicMethod("", ChildrenType, methodArgs2, _globalType);// create dynmic method
var ilGen = dynamicMethod.GetILGenerator();
var readField = _globalType.GetField("_read", BindingFlags.NonPublic | BindingFlags.Instance);
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, readField);
ilGen.Emit(OpCodes.Ldc_I4, 3214);
ilGen.Emit(OpCodes.Conv_I8);
ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());
ilGen.Emit(OpCodes.Ret);
Get = (GetItemDelegate)dynamicMethod.CreateDelegate(typeof(GetItemDelegate), this); // save method as Get variable
}
}
class Program
{
static void Main(string[] args)
{
var tmp = new test();
Console.WriteLine(tmp.Get());
Console.ReadLine();
}
}
}
以编辑中的示例为例:问题简单到字段访问和方法调用不正确;看这里:
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, readField);
ilGen.Emit(OpCodes.Ldc_I4, 3214);
ilGen.Emit(OpCodes.Conv_I8);
ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());
ilGen.Emit(OpCodes.Ret);
这里,\u read
是对viewAccessor的委托。ReadDouble
-即ReadDouble
是实例方法,viewAccessor
是目标实例。我们有两个选择:
- 对我们先前存储在
中的实例调用viewAccessor
ReadDouble
- 在代理上调用
invoke
// removed: ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());
ilGen.Emit(OpCodes.Callvirt, _read.GetType().GetMethod("Invoke"));
ilGen.Emit(OpCodes.Ret);
请注意,您必须使用除3214
以外的值,或者将文件/视图访问器的容量/大小更改为大于123
的值
但是,如果忘记\u read
,而是存储viewAccessor
,并调用virtreadMethod
,可能会更有效。例如:
private MemoryMappedViewAccessor _acc;
// ...
var viewAccessor = file.CreateViewAccessor(0, 123 * 1000);
_acc = viewAccessor;
var accField = _globalType.GetField("_acc",
BindingFlags.NonPublic | BindingFlags.Instance);
// ...
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, accField);
ilGen.Emit(OpCodes.Ldc_I4, 3214);
ilGen.Emit(OpCodes.Conv_I8);
ilGen.Emit(OpCodes.Callvirt, readMethod);
ilGen.Emit(OpCodes.Ret);
this.Get(1,2,3)
和this.\u read(2568)
之间的关系是什么?生成的方法是什么?GetItemDelegate
看起来像什么?基本上:我们如何重新编程?为什么这个方法有10个参数,而你的两个例子是:不?什么是\u dims
,它有多大?什么是\u shift
字段?基本上,我认为这在当前状态下是完全无法回答的。然而,我确实怀疑,如果您运行此过程,您将得到一个更有用的错误消息code(var I=0;I<\u dims.Length;I++){…}
工作正常。当方法获取1,2,3作为参数时,该循环将2568推到堆栈中。我尝试将其用作委托方法“\u read”的参数。需要更多的解释吗?是的。。。。你看到我问的那些问题了吗?基本上:你应该试着把它简化成一个可复制的例子,这里的人可以跑过去看看问题。这样做很有可能:你会发现问题所在;但如果你不这样做,这里的人(像我一样)很有可能会这样做。好的,我会尝试复制一个例子。谢谢,它成功了。随机选择数字123
和3214
,仅用于运行前面错误的示例。
// removed: ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());
ilGen.Emit(OpCodes.Callvirt, _read.GetType().GetMethod("Invoke"));
ilGen.Emit(OpCodes.Ret);
private MemoryMappedViewAccessor _acc;
// ...
var viewAccessor = file.CreateViewAccessor(0, 123 * 1000);
_acc = viewAccessor;
var accField = _globalType.GetField("_acc",
BindingFlags.NonPublic | BindingFlags.Instance);
// ...
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, accField);
ilGen.Emit(OpCodes.Ldc_I4, 3214);
ilGen.Emit(OpCodes.Conv_I8);
ilGen.Emit(OpCodes.Callvirt, readMethod);
ilGen.Emit(OpCodes.Ret);