Ç动态地使用C#编译$ C $ [英] Compiling code dynamically using C#

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

问题描述

我怎么能写C#code编译和运行动态生成的C#code。是否有周围的例子?

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

我是后是动态地建立一个C#类(或类),并在运行时运行它们。我想生成的类与其他C#类不是动态的交互。

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.

我已经看到,生成EXE或DLL文件的例子。我不是在这之后,我只是希望它编译一些C#code在内存中,然后运行它。例如,

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,

因此​​,这里是一个类是不是动态的,它会在我的C#程序集定义,只会改变在编译的时候,

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
    }
}

下面是我的类,它是动态的。我的C#code会生成这个类,并运行它,

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");
    }
}

所以结果是,在结束我的非动态code称之为ProcessValues​​,它会做一些其他的东西。动态code的一点​​是让我们或客户端自定义逻辑添加到软件中。

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.

感谢。

推荐答案

两种可能性:

  1. Reflection.Emit的
  2. <一个href="http://msdn.microsoft.com/en-us/library/system.$c$cdom.compiler.aspx">System.$c$cDom.Compiler
  1. Reflection.Emit
  2. System.CodeDom.Compiler

更新:

由于在评论部分请求,这里是一个完整的例子,说明Reflection.Emit的的使用情况,动态地构建一个类,并添加了一个静态方法吧:

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]);
    }
}

您可以把断点在你没有 NotDynamicClass 方法,看看他们是如何得到调用。

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

更新2:

下面是用codeDOM编译器的一个例子:

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#编译$ C $的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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