使用C#动态编译代码 [英] Compiling code dynamically using C#

查看:102
本文介绍了使用C#动态编译代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何编写C#代码来编译和运行动态生成的C#代码。有没有例子?



我之后是动态构建一个C#类(或类)并在运行时运行它们。我希望生成的类与其他不动态的C#类交互。



我看到生成exe或dll文件的例子。我不是这样,我只是希望它在内存中编译一些C#代码,然后运行它。例如,



所以这里是一个不是动态的类,它将在我的C#程序集中定义,只会在编译时更改

  public class NotDynamicClass 
{
private readonly List< string> values = new List< string>();

public void AddValue(string value)
{
values.Add(value);新评新新新旗新新新新旗新新旗200新新新新旗新新旗200新新新旗200 200新新新旗200 200新新新旗200 200 200新新新旗200 200 200新新新旗新新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗新旗/ code>

这是我的类是动态的。我的C#代码将生成这个类并运行它,

  public class DynamicClass 
{
public static void Main()
{
NotDynamicClass class = new NotDynamicClass();

class.AddValue(One);
class.AddValue(two);新评新醒旗200 200 200 200 200 -40 200 200 200 -40 -40 -40 -40 -40 -40新新200新新新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗旗代码将调用ProcessValues,它会做一些其他的东西。新新新新旗新新新旗新新新新旗新新旗新新旗旗新新新旗新新旗旗新1992新新新新旗新新旗旗新1992新新新新旗新新旗200新新新新旗新新旗200新新新新旗新新旗200新新新新旗新新旗200新新新新旗新旗200新新新新旗新旗200新新新新旗新旗200新新新新旗新旗200新新新新旗新旗200新新新新旗新旗200新新新新旗新新旗新旗新旗新旗新旗新新旗新新旗新旗新旗新新旗旗号旗新新旗新新旗新旗新旗新新旗旗号旗新新旗新新旗新旗新旗新新旗旗号旗新新旗新新旗新旗新旗新旗新新旗旗号旗新新旗新新旗新旗h2_lin>解决方案

两种可能性:


  1. Reflection.Emit

  2. System.CodeDom.Compiler


$ b $新评新新新旗新新新新旗新新新新旗新新旗新新旗新新旗新新旗新新旗新新旗旗新新旗新新新新旗新新旗旗新新旗新1992:动态构建一个类并添加一个静态方法:

  using System; 
使用System.Collections.Generic;
使用System.Reflection;
使用System.Reflection.Emit;

public class NotDynamicClass
{
private readonly List< string> values = new List< string>();

public void AddValue(string value)
{
values.Add(value);
}

public void ProcessValues()
{
foreach(var item in values)
{
Console.WriteLine(item);新评新新新新新旗新新新新旗新新新新旗新旗旗新旗旗新旗旗新新旗新旗旗新旗旗新新旗新旗旗新旗旗哨旗新新新新旗新旗新旗新旗新旗200新新新新旗新新旗新新旗新新旗新新旗新新旗新新旗2001- assemblyName = new AssemblyName(DynamicAssemblyDemo);
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name,false);
var typeBuilder = moduleBuilder.DefineType(DynamicClass,TypeAttributes.Public);

var methodBuilder = typeBuilder.DefineMethod(
Main,
MethodAttributes.Public | MethodAttributes.Static,
null,
new Type [0]
);

var il = methodBuilder.GetILGenerator();
var ctor = typeof(NotDynamicClass).GetConstructor(new Type [0]);
var addValueMi = typeof(NotDynamicClass).GetMethod(AddValue);
il.Emit(OpCodes.Newobj,ctor);
il.Emit(OpCodes.Stloc_0);
il.DeclareLocal(typeof(NotDynamicClass));
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldstr,One);
il.Emit(OpCodes.Callvirt,addValueMi);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldstr,Two);
il.Emit(OpCodes.Callvirt,addValueMi);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Callvirt,typeof(NotDynamicClass).GetMethod(ProcessValues));
il.Emit(OpCodes.Ret);
var t = typeBuilder.CreateType();
var mi = t.GetMethod(Main);
mi.Invoke(null,new object [0]); X-454545454545 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X-454545 X- c> NotDynamicClass
方法,看看如何调用它们。






更新2:



这是CodeDom编译器的一个例子:

  using System; 
使用System.CodeDom.Compiler;
使用System.Collections.Generic;
使用Microsoft.CSharp;

public class NotDynamicClass
{
private readonly List< string> values = new List< string>();

public void AddValue(string value)
{
values.Add(value);
}

public void ProcessValues()
{
foreach(var item in values)
{
Console.WriteLine(item);
}
}
}

类程序
{
public static void Main()
{
var provider = CSharpCodeProvider.CreateProvider(c#);
var options = new CompilerParameters();
var assemblyContainingNotDynamicClass = Path.GetFileName(Assembly.GetExecutingAssembly()。Location);
options.ReferencedAssemblies.Add(assemblyContainingNotDynamicClass);
var results = provider.CompileAssemblyFromSource(options,new []
{
@public class DynamicClass
{
public static void Main()
{
NotDynamicClass @class = new NotDynamicClass();
@ class.AddValue(One);
@ class.AddValue(Two);
@ class.ProcessValues();
}
}
});
if(results.Errors.Count> 0)
{
foreach(result.Errors中的var error)
{
Console.WriteLine(error);
}
}
else
{
var t = results.CompiledAssembly.GetType(DynamicClass);
t.GetMethod(Main)。Invoke(null,null);
}
}
}


How can I wrote C# code to compile and run dynamically generated C# code. Are there examples around?

What I am after is to dynamically build up a C# class (or classes) and run them at runtime. I want the generated class to interact with other C# classes that are not dynamic.

I have seen examples that generate exe or dll files. I am not after that, I just want it to compile some C# code in memory and then run it. For instance,

So here is a class which is not dynamic, it will be defined in my C# assembly and will only change at compile time,

public class NotDynamicClass
{
    private readonly List<string> values = new List<string>();

    public void AddValue(string value)
    {
        values.Add(value);
    }

    public void ProcessValues()
    {
        // do some other stuff with values
    }
}

Here is my class that is dynamic. My C# code will generate this class and run it,

public class DynamicClass
{
    public static void Main()
    {
        NotDynamicClass class = new NotDynamicClass();

        class.AddValue("One");
        class.AddValue("two");
    }
}

So the result is that at the end my non dynamic code would call ProcessValues and it would do some other stuff. The point of the dynamic code is to allow us or the client to add custom logic to the software.

Thanks.

解决方案

Two possibilities:

  1. Reflection.Emit
  2. System.CodeDom.Compiler


UPDATE:

As request in the comments section here's a full example illustrating the usage of Reflection.Emit to dynamically build a class and add a static method to it:

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;

public class NotDynamicClass
{
    private readonly List<string> values = new List<string>();

    public void AddValue(string value)
    {
        values.Add(value);
    }

    public void ProcessValues()
    {
        foreach (var item in values)
        {
            Console.WriteLine(item);
        }
    }
}

class Program
{
    public static void Main()
    {
        var assemblyName = new AssemblyName("DynamicAssemblyDemo");
        var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
        var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, false);
        var typeBuilder = moduleBuilder.DefineType("DynamicClass", TypeAttributes.Public);

        var methodBuilder = typeBuilder.DefineMethod(
            "Main",
            MethodAttributes.Public | MethodAttributes.Static,
            null,
            new Type[0]
        );

        var il = methodBuilder.GetILGenerator();
        var ctor = typeof(NotDynamicClass).GetConstructor(new Type[0]);
        var addValueMi = typeof(NotDynamicClass).GetMethod("AddValue");
        il.Emit(OpCodes.Newobj, ctor);
        il.Emit(OpCodes.Stloc_0);
        il.DeclareLocal(typeof(NotDynamicClass));
        il.Emit(OpCodes.Ldloc_0);
        il.Emit(OpCodes.Ldstr, "One");
        il.Emit(OpCodes.Callvirt, addValueMi);
        il.Emit(OpCodes.Ldloc_0);
        il.Emit(OpCodes.Ldstr, "Two");
        il.Emit(OpCodes.Callvirt, addValueMi);
        il.Emit(OpCodes.Ldloc_0);
        il.Emit(OpCodes.Callvirt, typeof(NotDynamicClass).GetMethod("ProcessValues"));
        il.Emit(OpCodes.Ret);
        var t = typeBuilder.CreateType();
        var mi = t.GetMethod("Main");
        mi.Invoke(null, new object[0]);
    }
}

You could put breakpoints inside your not NotDynamicClass methods and see how they get invoked.


UPDATE 2:

Here's an example with CodeDom compiler:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Microsoft.CSharp;

public class NotDynamicClass
{
    private readonly List<string> values = new List<string>();

    public void AddValue(string value)
    {
        values.Add(value);
    }

    public void ProcessValues()
    {
        foreach (var item in values)
        {
            Console.WriteLine(item);
        }
    }
}

class Program
{
    public static void Main()
    {
        var provider = CSharpCodeProvider.CreateProvider("c#");
        var options = new CompilerParameters();
        var assemblyContainingNotDynamicClass = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
        options.ReferencedAssemblies.Add(assemblyContainingNotDynamicClass);
        var results = provider.CompileAssemblyFromSource(options, new[] 
        { 
@"public class DynamicClass
{
    public static void Main()
    {
        NotDynamicClass @class = new NotDynamicClass();
        @class.AddValue(""One"");
        @class.AddValue(""Two"");
        @class.ProcessValues();
    }
}"
        });
        if (results.Errors.Count > 0)
        {
            foreach (var error in results.Errors)
            {
                Console.WriteLine(error);
            }
        }
        else
        {
            var t = results.CompiledAssembly.GetType("DynamicClass");
            t.GetMethod("Main").Invoke(null, null);
        }
    }
}

这篇关于使用C#动态编译代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆