我需要一个性能增强的Activator.CreateInstance()并且Miron Abramson发现了这篇文章,它使用工厂在IL中创建实例然后缓存它.(我已经在Miron Abramson的网站上包含了以下代码,以防它以某种方式消失).我是IL Emit代码的新手,除了Activator.CreateInstance()之外的任何东西,用于实例化一个类,任何帮助都会非常感激.
我的问题是我需要创建一个带有参数的ctor对象的实例.我看到有一种传递参数类型的方法,但有没有办法传入ctor参数的值?
如果可能的话,我想使用类似于CreateObjectFactory<T>(params object[] constructorParams)我想要实例化的某些对象的方法可能有超过1个ctor param.
// Source: http://mironabramson.com/blog/post/2008/08/Fast-version-of-the-ActivatorCreateInstance-method-using-IL.aspx
public static class FastObjectFactory
{
private static readonly Hashtable creatorCache = Hashtable.Synchronized(new Hashtable());
private readonly static Type coType = typeof(CreateObject);
public delegate object CreateObject();
///
/// Create an object that will used as a 'factory' to the specified type T
///
public static CreateObject CreateObjectFactory() where T : class
{
Type t = typeof(T);
FastObjectFactory.CreateObject c = creatorCache[t] as FastObjectFactory.CreateObject;
if (c == null) …Run Code Online (Sandbox Code Playgroud) 请参阅代码段
public interface I0
{
void f0();
}
public struct S0:I0
{
void I0.f0()
{
}
}
public class A<E> where E :I0
{
public E e;
public void call()
{
e.f0();
}
}
Run Code Online (Sandbox Code Playgroud)
这是用于调用的IL代码()
.maxstack 8
L_0000: ldarg.0
L_0001: ldflda !0 Temp.A`1<!E>::e
L_0006: constrained !E
L_000c: callvirt instance void Temp.I0::f0()
L_0011: ret
Run Code Online (Sandbox Code Playgroud)
参见约束的参考
约束前缀也可用于在值类型上调用接口方法,因为可以使用MethodImpl更改实现接口方法的值类型方法.如果未使用约束前缀,则强制编译器在编译时选择要绑定到哪个值类型的方法.使用约束前缀允许MSIL在运行时绑定到实现接口方法的方法,而不是在编译时绑定.
这意味着它将调用一个包含接口方法代码f0的方法而不用装箱结构.
在C#中,如上所述GenericClass是否存在任何其他方式没有装箱的caling接口方法?
这是一个相当简单的泛型类.通用参数被约束为引用类型.IRepository并且DbSet还包含相同的约束.
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : class, IEntity
{
protected readonly DbSet<TEntity> _dbSet;
public void Insert(TEntity entity)
{
if (entity == null)
throw new ArgumentNullException("entity", "Cannot add null entity.");
_dbSet.Add(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
编译的IL包含box指令.这是发布版本(虽然调试版本也包含它).
.method public hidebysig newslot virtual final
instance void Insert(!TEntity entity) cil managed
{
// Code size 38 (0x26)
.maxstack 8
IL_0000: ldarg.1
>>>IL_0001: box !TEntity
IL_0006: brtrue.s IL_0018
IL_0008: ldstr "entity"
IL_000d: ldstr "Cannot add null entity."
IL_0012: …Run Code Online (Sandbox Code Playgroud) 我正在研究C#(IL)的中间语言,并且遇到了以下代码: -
//Add.il
//Add Two Numbers
.assembly extern mscorlib {}
.assembly Add
{
.ver 1:0:1:0
}
.module add.exe
.method static void main() cil managed
{
.maxstack 2
.entrypoint
ldstr "The sum of 50 and 30 is = "
call void [mscorlib]System.Console::Write (string)
ldc.i4.s 50
ldc.i4 30
add
call void [mscorlib]System.Console::Write (int32)
ret
}
Run Code Online (Sandbox Code Playgroud)
我是理解IL的初学者,但我知道Main在上面的例子中使用的这些非常基本的指令的含义.
我的问题是,ldc.i4.s用于加载50的指令和ldc.i4用于将30加载到评估堆栈的指令之间是否存在任何差异.
编译器如何决定使用哪个指令(在这两个指令中)以及何时使用?
我对MSIL和托管代码感到困惑他们是相同还是不同?我的意思是说,当我们构建C#代码时会发生什么?
哪一个是对的
C# Code ? C# compiler ? Managed Code ? MSIL
要么
C# Code ? C# compiler ? MSIL
请提供真实的参考或链接以支持您的答案.
我写了一个简单的程序来研究IL的工作原理:
void Main()
{
int a=5;
int b=6;
if (a<b) Console.Write("333");
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
IL:
IL_0000: ldc.i4.5
IL_0001: stloc.0
IL_0002: ldc.i4.6
IL_0003: stloc.1
IL_0004: ldloc.0
IL_0005: ldloc.1
IL_0006: bge.s IL_0012
IL_0008: ldstr "333"
IL_000D: call System.Console.Write
IL_0012: call System.Console.ReadLine
Run Code Online (Sandbox Code Playgroud)
我正在努力了解实施的效率:
在#1行(IL代码),它将值5推送到堆栈上(4个字节,即int32)
在第2行(IL代码),它从堆栈POP到局部变量.
接下来的两行也是如此.
然后,它将这些局部变量加载到堆栈上,然后进行评估bge.s.
问题#1
他为什么要将局部变量加载到堆栈中?值已经在堆栈中.但是为了把它们放在局部变量中,他将它们加以限制.这不是浪费吗?
我的意思是,为什么代码不能像:
IL_0000: ldc.i4.5
IL_0001: ldc.i4.6
IL_0002: bge.s IL_0004
IL_0003: ldstr "333"
IL_0004: call System.Console.Write
IL_0005: call System.Console.ReadLine
Run Code Online (Sandbox Code Playgroud)
我的代码示例只有5行代码.那50,000,000行代码呢?IL会发出大量额外的代码
问题2
查看代码地址:

ps我在+释放模式下使用Optimize标志
我正在使用ANTLR构建一个简单的.NET for .NET,将字符串中的脚本转换为Dynamic Method.我的第一个想法是转换为IL操作码,但现在我正在阅读有关DM创建的表达式树.似乎我可以使用表达式树生成任何方法,就像IL代码一样?
谢谢!
如果我有这样的代码:
public class Program
{
public static void Main()
{
string bar = "";
int foo = 24;
}
}
Run Code Online (Sandbox Code Playgroud)
我可以Main使用以下方法获取声明的局部变量:
var flag = BindingFlags.Static | BindingFlags.Public;
var fields = typeof(Program).GetMethod("Main", flags).GetMethodBody().LocalVariables;
Run Code Online (Sandbox Code Playgroud)
这将返回一个IList<LocalVariableInfo>与LocalVariableInfo只有三个属性:IsPinned,LocalIndex和LocalType.所以没有Name财产存在.
我想知道的是你可以看到生成的变量名称IL code:
.method public hidebysig static void Main() cil managed
{
.entrypoint
// Code size 11 (0xb)
.maxstack 1
.locals init ([0] string bar,
[1] int32 foo)
IL_0000: nop
IL_0001: ldstr …Run Code Online (Sandbox Code Playgroud) 我发现C#4.0中的"可选参数"功能非常有趣,所以我试图弄清楚它们是如何实现的.所以我写了一个像这样的方法:
private static void A(int a = 5) { }
Run Code Online (Sandbox Code Playgroud)
编译它,然后在IL DASM中反编译它,这是IL代码:
.method private hidebysig static void A([opt] int32 a) cil managed
{
.param [1] = int32(0x00000005)
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method Program::A
Run Code Online (Sandbox Code Playgroud)
它的元数据中有这个:
(1)ParamToken:(08000002)名称:标志:[可选] [HasDefault](00001010)默认值:(I4)5
所以我按照线索写了一个像这样的方法:
private static void B([Optional, DefaultParameterValue(78)]int b) { }
Run Code Online (Sandbox Code Playgroud)
编译并反编译它,我发现C#编译器为方法A和B生成了几乎相同的MSIL代码(名称除外).
正如我们所看到的,IL代码中没有属性的迹象,而且感觉不对,所以我写了一个这样的自定义属性:
[AttributeUsage(AttributeTargets.Parameter)]
public class MyTestAttribute : Attribute
{
}
Run Code Online (Sandbox Code Playgroud)
然后在方法C中使用它,如下所示:
private static void C([MyTest]int c) { }
Run Code Online (Sandbox Code Playgroud)
编译它然后反编译它,哈哈,我发现了这个:
.method private hidebysig static void …Run Code Online (Sandbox Code Playgroud) 我正在浏览你在C#或.NET中看到的最奇怪的角落是什么?,这段代码让我思考了一下:
public class Program
{
delegate void HelloDelegate(Strange bar);
[STAThread()]
public static void Main(string[] args)
{
Strange bar = null;
var hello = new DynamicMethod("ThisIsNull",
typeof(void), new[] { typeof(Strange) },
typeof(Strange).Module);
ILGenerator il = hello.GetILGenerator(256);
il.Emit(OpCodes.Ldarg_0);
var foo = typeof(Strange).GetMethod("Foo");
il.Emit(OpCodes.Call, foo);
il.Emit(OpCodes.Ret);
var print = (HelloDelegate)hello.CreateDelegate(typeof(HelloDelegate));
print(bar);
Console.ReadLine();
}
internal sealed class Strange
{
public void Foo()
{
Console.WriteLine(this == null);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我确实理解代码的作用,但我不明白为什么它有效.是不是喜欢这样做null.Foo()?它就好像Foo()是静态的,而是被调用:Strange.Foo();.
你能告诉我我错过了什么吗?
il ×10
c# ×9
.net ×6
cil ×2
antlr ×1
c#-4.0 ×1
compilation ×1
dsl ×1
generics ×1
parameters ×1
performance ×1
reflection ×1