我有一些代码使用MethodInfo在生成的类型上找到的泛型方法.为了避免一些反思,我让代码使用了
ldtoken Method
ldtoken Type
call GetMethodFromHandle(RuntimeMethodHandle,RunTimeTypeHandle)
Run Code Online (Sandbox Code Playgroud)
用于在编译时生成MethodInfos的模式.
但是,如果methodInfo属于泛型类型,并且本身是泛型方法,那么事情就变得棘手了.这里有一些代码只是生成一个GM,它发出了一个开放版本的methodInfo.如果我调用它来检索方法而不是尝试在特定类型上关闭它,我会得到一个令人困惑的异常::
System.Reflection.MethodInfo
GM[M]()不是GenericMethodDefinition.MakeGenericMethod只能在MethodBase.IsGenericMethodDefinition为true的方法上调用.
这是相关代码::
var aBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.RunAndSave);
var mBuilder = aBuilder.DefineDynamicModule(aBuilder.GetName().Name, true);
var typeBuilder = mBuilder.DefineType("NameSpace.Generic`1",TypeAttributes.AutoClass | TypeAttributes.Sealed | TypeAttributes.Public,typeof(object));
var TypeGenerics = typeBuilder.DefineGenericParameters(new[] { "T" });
var methodBuilder = typeBuilder.DefineMethod("GM", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig);
var methodGenerics = methodBuilder.DefineGenericParameters(new[] { "M" });
methodBuilder.SetSignature(typeof(MethodInfo), null, null, Type.EmptyTypes, null, null);
var ilgenerator = methodBuilder.GetILGenerator();
var typeBuilderClosedOverT = typeBuilder.MakeGenericType(TypeGenerics);
ilgenerator.Emit(OpCodes.Ldtoken, methodBuilder);
ilgenerator.Emit(OpCodes.Ldtoken, typeBuilderClosedOverT);
ilgenerator.Emit(OpCodes.Call,
typeof(MethodBase).GetMethod(
"GetMethodFromHandle",
BindingFlags.Public | …Run Code Online (Sandbox Code Playgroud) 我有以下代码
using System;
class Pankaj
{
public static int Main()
{
int returnValue=0;
try
{
return returnValue;
throw new Exception();
}
catch(Exception ex){
return returnValue;
}
finally
{
returnValue++;
}
return returnValue;
}
}
Run Code Online (Sandbox Code Playgroud)
上面代码生成的MSIL是:
.method public hidebysig static int32 Main() cil managed
{
.entrypoint
// Code size 18 (0x12)
.maxstack 2
.locals init (int32 V_0,
int32 V_1)
IL_0000: ldc.i4.0
IL_0001: stloc.0
.try
{
.try
{
IL_0002: ldloc.0
IL_0003: stloc.1
IL_0004: leave.s IL_0010
} // end .try
catch [mscorlib]System.Exception
{ …Run Code Online (Sandbox Code Playgroud) 我正在以一种方式深入克隆对象图.我将有多个线程非常快速地克隆图形,以便它们可以在某些状态下播放并丢弃结果,如果它们不感兴趣,则返回到原始状态再次尝试.
我目前正在通过二进制序列化使用深度克隆,尽管它有效但速度并不快.我见过像protobuf这样的其他库,但我的对象图中的类可以在外部程序集中定义,继承自主程序集中的类,并且如果可能的话,不希望在那些使用程序集中添加任何复杂性.
我遇到的一个有趣的事情是使用自动生成的IL进行克隆.它似乎还没有完成,我已发布,看看作者是否已经做了更多,但我猜不是.有没有其他人通过IL开发或看到更全功能的深度克隆方式?或者另一种快速的方法?
当Debug.Assert()源代码中存在方法调用并且我在发布模式下编译时,编译器是否会生成IL,Debug.Assert()即使它没有被调用?
我们的一位开发人员最近添加了一个Assert,显示有关内部安全性的信息.有人可以查看发布模式IL并找出断言的文本吗?
我已经检测到遗留第三方程序集上的一些缺陷,我们正在使用我们的代码对它们进行解压缩.我想修复它们但由于我没有源代码,我需要直接修改字节码.这些变化非常简单(为OR更改AND,为某些行更改NOP).
是否有编辑来做这种事情?使用十六进制编辑器进行工作将是最后一个选项,我会想知道我对光标有什么指示......
所以,我最近做了一些实验,发现似乎Reflection.Emit不支持ECMA规范中的所有操作码.缺少3个操作码:
ldelem.anystelem.any no. (字首)这些操作码是否在Reflection API中不受支持,或者是否有某种方法可以生成它们?
我正在使用编译器System.Reflection.Emit,我得到JIT限制错误,我无法弄清楚.问题出现在我的函数句柄实现中.即生成代码
function foo() { }
f = foo;
f();
Run Code Online (Sandbox Code Playgroud)
由于我无法控制的规范,语言是动态类型的,所以我不知道f在编译时会有多少参数.为了解决这个问题,我生成了一个新方法,而不是发出一个Ldftnfor foo,?foo它接受一个在调用表达式中给出的参数数组,然后将它们推送到eval堆栈中foo.CLR允许这样做吗?
我现在得到的是"JIT遇到内部限制"异常(或者"CLR检测到无效程序",如果我保存程序集并运行它而不是从内存中调用它),堆栈跟踪显示它发生在?foo.这就是我正在生成的IL.
.method private instance class [MylibInterop]MylibInterop.MylibValue
'?foo'(class [MylibInterop]MylibInterop.MylibValue[] A_1) cil managed
{
// Code size 90 (0x5a)
.maxstack 10
.locals init (int32 V_0,
int32 V_1)
IL_0000: ldarg.1
IL_0001: call instance int32 [mscorlib]System.Array::get_Length()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4 0x0
IL_000d: ble IL_001d
IL_0012: ldstr "Too many arguments to lambda call"
IL_0017: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_001c: …Run Code Online (Sandbox Code Playgroud) 是否存在将单个.NET程序集拆分为完整程序集子集的实用程序?即ILMerge.exe的"功能逆转"?
当然,如果它必须跟踪类,函数等之间的依赖性等,那么这个工具很难产生.
但是,我正在寻找的情况是我有一个非常大(数百MB)的混合模式程序集,主要是静态类和静态方法,基本上只是一个函数库.虽然,与一些DLLMain初始化和类似.
我想要的是能够在我希望保留在子集程序集中的特定静态类上指定静态方法列表.从技术上讲,这应该是可能的,因为程序集只是具有标准格式的二进制信息.
这是否存在或如何制作?或者为什么这不切实际?
我有一些标有的辅助方法[Conditional("XXX")].目的是在仅存在XXX条件编译符号时使方法有条件地编译.我们使用它来调试和跟踪功能,它运行良好.
在我研究条件编译如何工作的过程中,我发现有几个来源说明用Conditional属性标记的方法将放在IL中,但是不会执行对方法的调用.
代码如何编译成IL而不执行?如何验证行为实际上是如上所述?我没有对IL做过多少工作,所以我的技能在这个方面都很弱.
strfld如果将其所有者设置为该类并且关闭JIT检查,则可以使用动态方法中的操作码存储在类的只读字段中.一个例子是在这里.然而,这种方法不适用于来自F#的类,即FSharpOption.请分析以下示例:
using Microsoft.FSharp.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
#if true
using MyType = Microsoft.FSharp.Core.FSharpOption<string>;
#else
using MyType = System.Tuple<string>;
#endif
namespace ConsoleApplication27
{
class Program
{
static void Main(string[] args)
{
var something = new MyType("test");
var dynMethod = new DynamicMethod("ChangeField", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(void), new [] { typeof(MyType) }, typeof(MyType), true);
var generator = dynMethod.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldstr, "success");
generator.Emit(OpCodes.Stfld, typeof(MyType).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)[0]);
generator.Emit(OpCodes.Ret);
var …Run Code Online (Sandbox Code Playgroud) il ×10
c# ×8
.net ×5
cil ×2
reflection ×2
.net-4.5 ×1
bytecode ×1
clone ×1
disassembly ×1
f# ×1
ilmerge ×1
mixed-mode ×1