c# - 使用 Roslyn 创建部分类 - 一个在运行时编译的类

标签 c# dynamic roslyn c#-6.0

我有一个类(HelloWorld.cs):

public partial class HelloWorld
{
    public void SayHello()
    {
        var message = "Hello, World!";
        var length = message.Length;
        Console.WriteLine("{1} {0}", message, length);
    }

}

上面的类属性BuildAction = Compile

我在单独的文件中还有另一个类(HelloWorldExtend.cs):

public partial class HelloWorld
    {
        public void SayHelloExtend()
        {
            var message = "Hello, World Extended!";
            var length = message.Length;
            Console.WriteLine("{1} {0}", message, length);
        }

    }

但是该类的属性是:BuildAction = None 和 Copy to output directory = Copy if newer

现在主要方法: 它使用 Roslyn。

static void Main(string[] args)
        {
            var code = File.ReadAllText("HelloWorldExtend.cs");
            var tree = SyntaxFactory.ParseSyntaxTree(code);

            var compilation = CreateCompilation(tree);
            var model = compilation.GetSemanticModel(tree);            

            ExecuteCode(compilation);

            Console.ReadLine();

        }

    private static void ExecuteCode(CSharpCompilation compilation)
            {
                using (var stream = new MemoryStream())
                {
                    compilation.Emit(stream);

                    var assembly = Assembly.Load(stream.GetBuffer());
                    var type = assembly.GetType("HelloWorld");
                    var greeter = Activator.CreateInstance(type);

                    var methodextend = type.GetMethod("SayHelloExtend");
                    methodextend.Invoke(HelloWorld, null);
                    //Works perfect

                    var method = type.GetMethod("SayHello");
                    method.Invoke(greeter, null);

 //method is returned null and gives an error : {"Object   reference
 not set to an instance of an object."}

                }
            }

是否可以使用 roslyn 为现有类提供与常规分部类相同的效果,其中一个类在构建期间编译,另一个类在运行时在同一程序集中编译 .

最佳答案

简短回答:不。

原始程序集已经编译完毕。 HelloWorld 的类定义已转换为 IL,并且在编译时没有其他源文件来构成分部类的其他部分。

您可以通过将部分文件的两个部分作为源提供来创建一个包含其自己版本的 HelloWorld程序集。

但是

看起来您可以简单地扩展原始类,并可以选择使当前编译的类成为抽象类。

public abstract class HelloWorldBase
{
    public void SayHello()
    {
        var message = "Hello, World!";
        var length = message.Length;
        Console.WriteLine("{1} {0}", message, length);
    }
}

在类上面设置属性BuildAction = Compile

public class HelloWorld : HelloWorldBase
{
    public void SayHelloExtend()
    {
        var message = "Hello, World Extended!";
        var length = message.Length;
        Console.WriteLine("{1} {0}", message, length);
    }
}

确保as part of your compilation, you reference the assembly containing HelloWorldBase before actually compiling the sources :

 compilation.AddReferences(new MetadataFileReference(typeof(HelloWorldBase).Assembly.location));

这应该有效。

关于c# - 使用 Roslyn 创建部分类 - 一个在运行时编译的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32806630/

相关文章:

c# - 将 SQL Server 错误返回给用户

c# - 将类作为参数传递

c# toolstrip 不在 menustrip 下停靠

python - 创建基于动态更改列的公式以在 Pandas Dataframe 列中设置值

c# - 是否可以在 Visual Studio 中配置具有特定逻辑的区域快捷方式?

c# - 为什么在转换为单例时我失去了分数(13.5 变成了 135)?

Java动态绑定(bind)的困惑

java - java中动态调用子类的方法

c# - 如何获取 IMethodSymbol 的语句?

c# - 如何使 csc.exe C# 6 感知