标签: il

如何在Activator.CreateInstance中传递ctor args或使用IL?

我需要一个性能增强的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)

.net parameters performance il createinstance

11
推荐指数
2
解决办法
2万
查看次数

除了泛型类之外,还有其他方法可以调用结构的接口方法而不需要装箱吗?

请参阅代码段

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接口方法?

c# il

11
推荐指数
1
解决办法
1295
查看次数

为什么'box'指令是针对泛型发出的?

这是一个相当简单的泛型类.通用参数被约束为引用类型.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# generics il

11
推荐指数
2
解决办法
603
查看次数

ldc.i4.s和ldc.i4有什么区别?

我正在研究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加载到评估堆栈的指令之间是否存在任何差异.

编译器如何决定使用哪个指令(在这两个指令中)以及何时使用?

.net c# il cil

11
推荐指数
1
解决办法
4722
查看次数

MSIL与.NET中的托管代码相同吗?

我对MSIL托管代码感到困惑他们是相同还是不同?我的意思是说,当我们构建C#代码时会发生什么?

哪一个是对的

C# Code ? C# compiler ? Managed Code ? MSIL

要么

C# Code ? C# compiler ? MSIL

请提供真实的参考或链接以支持您的答案.

.net c# il compilation

10
推荐指数
2
解决办法
4123
查看次数

在.net中的IL和堆栈实现?

我写了一个简单的程序来研究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

查看代码地址:

在此输入图像描述

  • IL_0009地址在哪里?它应该是顺序的吗?

ps我在+释放模式下使用Optimize标志

.net c# compiler-construction il

10
推荐指数
3
解决办法
1033
查看次数

C#动态方法 - IL与表达式树

我正在使用ANTLR构建一个简单的.NET for .NET,将字符串中的脚本转换为Dynamic Method.我的第一个想法是转换为IL操作码,但现在我正在阅读有关DM创建的表达式树.似乎我可以使用表达式树生成任何方法,就像IL代码一样?

谢谢!

代码:https://github.com/ricardoborges/NPortugol2

c# dsl il antlr expression-trees

10
推荐指数
1
解决办法
1289
查看次数

为什么不能使用Reflection获取局部变量名?

如果我有这样的代码:

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,LocalIndexLocalType.所以没有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# reflection il local-variables

10
推荐指数
3
解决办法
1722
查看次数

[opt]在MSIL中意味着什么?

我发现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)

.net c# il cil c#-4.0

9
推荐指数
1
解决办法
1419
查看次数

为什么这样做?从IL执行方法没有实例

我正在浏览你在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();.

你能告诉我我错过了什么吗?

.net c# il

9
推荐指数
1
解决办法
193
查看次数