我已经编写了.NET和C#多年,但最近才DynamicMethod在反射的上下文中遇到了类型和动态汇编的概念.它们似乎总是在IL(运行时代码)生成中使用.
不幸的是,MSDN在定义动态汇编/方法属性以及它们应该用于什么方面做得非常糟糕.能不能在这里启发我吗?与DLR有什么关系吗?它们如何与运行时静态(正常)生成的程序集和方法不同?我应该知道如何以及何时使用它们?
假设我有以下表达式:
Expression<Action<T, StringBuilder>> expr1 = (t, sb) => sb.Append(t.Name);
Expression<Action<T, StringBuilder>> expr2 = (t, sb) => sb.Append(", ");
Expression<Action<T, StringBuilder>> expr3 = (t, sb) => sb.Append(t.Description);
Run Code Online (Sandbox Code Playgroud)
我希望能够将这些编译成与以下内容等效的方法/委托:
void Method(T t, StringBuilder sb)
{
sb.Append(t.Name);
sb.Append(", ");
sb.Append(t.Description);
}
Run Code Online (Sandbox Code Playgroud)
解决这个问题的最佳方法是什么?我希望它表现良好,理想情况下性能与上述方法相当.
更新 所以,虽然似乎没有办法在C#3中直接执行此操作,有没有办法将表达式转换为IL,以便我可以将它与System.Reflection.Emit一起使用?
我继承了使用DynamicMethod在运行时生成方法的代码.我还需要修改一些正在生成的代码.
因为我是MSIL的n00b,所以我希望能够在Reflector中加载生成的代码,并确保代码执行我祈祷的功能;)
只是,我无法弄清楚如何将"Anonymousously Hosted DynamicMethods Assembly"序列化到磁盘.这可能吗?如果是这样,怎么样?
我正在制作一个声音合成程序,用户可以创建自己的声音进行基于节点的合成,创建振荡器,滤波器等...
程序将节点编译成中间语言,然后通过ILGenerator和DynamicMethod转换为MSIL.
它适用于存储所有操作和数据的数组,但如果我能够使用指针允许我稍后执行一些位级操作,它会更快
PD:速度非常重要!!
我注意到一个DynamicMethod构造函数覆盖有一个方法属性,一个是UnsafeExport,但我不能使用它,因为唯一有效的组合是Public + Static
这就是我想要做的事情,它会抛出一个VerificationException :(只是为指针赋值)
//Testing delegate
unsafe delegate float TestDelegate(float* data);
//Inside the test method (wich is marked as unsafe)
Type ReturnType = typeof(float);
Type[] Args = new Type[] { typeof(float*) };
//Can't use UnamangedExport as method atribute:
DynamicMethod M = new DynamicMethod(
"HiThere",
ReturnType, Args);
ILGenerator Gen = M.GetILGenerator();
//Set the pointer value to 7.0:
Gen.Emit(OpCodes.Ldarg_0);
Gen.Emit(OpCodes.Ldc_R4, 7F);
Gen.Emit(OpCodes.Stind_R4);
//Just return a dummy value:
Gen.Emit(OpCodes.Ldc_R4, 20F);
Gen.Emit(OpCodes.Ret);
var del = (TestDelegate)M.CreateDelegate(typeof(TestDelegate));
float* data = …Run Code Online (Sandbox Code Playgroud) 在搜索了stackoverflow和googling很多之后,为DynamicMethods调试代码提供的调试解决方案似乎已经过时且非常笨拙.
当然,在LCG(轻量级代码生成)发布后的4年或更长时间内,有人必须找到更好的方法.
您发现什么是验证您编写和调试它的动态IL的最简单方法?
你使用peverify或ILDasm还是别的什么?这两个工具需要将程序集写入磁盘,但DynamicMethod不提供任何直接的方法.
显然,WinDbg aso提供了一种查看IL的方法,但处理这个问题非常尴尬.
像VisualStudio 2010这样的插件将是理想的选择.
有任何想法吗?
我正在尝试使用DynamicMethod调用非托管类似printf的函数.在运行时我得到一个
BadImageFormatException:找不到索引.(HRESULT异常:0x80131124)
这是运行时的限制还是我的发出代码错了?
public class Program
{
[DllImport("msvcrt40.dll",CallingConvention = CallingConvention.Cdecl)]
public static extern int printf(string format, __arglist);
static void Main(string[] args) {
var method = new DynamicMethod("printf", typeof(void), new Type[0], true);
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldstr, " %s=%d\n");
il.Emit(OpCodes.Ldstr, "a");
il.Emit(OpCodes.Ldc_I4_0);
il.EmitCall(OpCodes.Call, typeof(Program).GetMethod("printf", BindingFlags.Public | BindingFlags.Static), new Type[] { typeof(string), typeof(int) });
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ret);
var action = (Action)method.CreateDelegate(typeof(Action));
action.Invoke();
}
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试生成带有StringBuilder的代码,并将类中所有属性的值写入字符串.我有以下内容,但我目前在以下代码中获得了"无效方法令牌":
public static DynamicAccessor<T> CreateWriter(T target) //Target class to *serialize*
{
DynamicAccessor<T> dynAccessor = new DynamicAccessor<T>();
MethodInfo AppendMethod = typeof(StringBuilder).GetMethod("Append", new[] { typeof(Object) }); //Append method of Stringbuilder
var method = new DynamicMethod("ClassWriter", typeof(StringBuilder), new[] { typeof(T) }, typeof(T), true);
var generator = method.GetILGenerator();
LocalBuilder sb = generator.DeclareLocal(typeof(StringBuilder)); //sb pointer
generator.Emit(OpCodes.Newobj, typeof(StringBuilder)); //make our string builder
generator.Emit(OpCodes.Stloc, sb); //make a pointer to our new sb
//iterate through all the instance of T's props and sb.Append their values.
PropertyInfo[] props = …Run Code Online (Sandbox Code Playgroud) 感谢Hans Passant在这里回答我的问题: 如何从DynamicMethod获取IL bytearray?
我能够起床和跑步.我现在正在尝试解决在IL发出的元数据令牌,以查看正在调用哪些方法,或者什么不是.我能够解决方法体中的下一个标记是一个调用.我正在使用来自Mono.ReflectionMethodBodyReader的一些代码.
static byte[] GetILByteArray(Delegate @delegate){
// does stuff mentioned in other thread
}
...
Expression<Action> foo = () => Console.WriteLine(0);
var compiled = foo.Compile();
var bytes = GetILByteArray(compiled);
int index =Array.FindIndex(bytes,b=>GetOpCode(b).OperandType == OperandType.InlineMethod);
var token = BitConverter.ToInt32(bytes,index+1);
compiled.Method.Module.ResolveMember(token);
Run Code Online (Sandbox Code Playgroud)
引发异常,说明该域中的令牌是不可解析的.这里有人有诀窍吗?我应该尝试传递代理通用参数还是完全没用?
我现在正在考虑为表达式树的代表编写一个反编译器的想法,我真的希望能够使用我自己编译为测试用例的表达式树,因为我总是可以回到原始版本并进行比较.
请考虑以下简单代码:
using System;
class Test
{
delegate int FooDelegate(int i);
FooDelegate Foo = FooImplementation;
static int FooImplementation(int i)
{
return i + 1;
}
public static void Main()
{
Foo(1);
}
}
Run Code Online (Sandbox Code Playgroud)
我想做的是将一些调试代码注入到Foo委托中,这相当于:
FooDelegate Foo = delegate(int i)
{
try
{
DebugPrologue();
return FooImplementation(i);
}
finally
{
DebugEpilogue();
}
};
Run Code Online (Sandbox Code Playgroud)
扭曲的是我必须能够在运行时执行此操作,因此编译时和后处理方法是不可能的.
我的初始方法使用Delegate.Combine()将序言和结尾方法添加到Foo委托.唉,这不会起作用,因为它会回报价值.
我目前的想法是使用System.Reflection.Emit和DynamicMethod作为潜在的解决方案.据我所知,我需要为FooImplementation获取MethodInfo,获取它的MethodBody,将其转换为DynamicMethod并将try-finally块注入其中.
不幸的是,我完全不知道该怎么做.谁愿意伸出援助之手?或者你有另一个(最好更简单)的想法?
编辑:这里的用例是调试OpenGL绑定(http://www.opentk.com).我们必须注入2226种具有完全不同参数的方法,因此需要采用一般方法.
我创建了一个非常简单的函数,它执行以下操作:
public static object[] ToArray(int ID) {
return new object[4];
}
Run Code Online (Sandbox Code Playgroud)
这是生成MSIL的代码.为什么这会引发"操作可能破坏运行时的稳定性"异常?我无法发现任何错误; 它完美匹配Reflector/Reflexil中的组件.
// create method
Type arrayType = typeof(object[]);
Type intType = typeof(int);
DynamicMethod dm = new DynamicMethod(methodName, arrayType, new Type[] { intType });
ILGenerator il = dm.GetILGenerator();
// create the array -- object[]
il.Emit(OpCodes.Ldc_I4, 4);
il.Emit(OpCodes.Newarr, typeof(object));
il.Emit(OpCodes.Stloc_0);
// return the array
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
return dm;
object result = dm.Invoke(null, new object[] { 1 });
Run Code Online (Sandbox Code Playgroud) dynamicmethod ×10
c# ×9
cil ×4
.net ×3
.net-4.0 ×1
debugging ×1
ilgenerator ×1
lambda ×1
linq ×1
opentk ×1
pointers ×1
reflection ×1
token ×1
unsafe ×1