it编程 > 编程语言 > Asp.net

C#通过脚本实现接口的示例详解

22人参与 2025-05-16 Asp.net

以前c#脚本用的委托注入模式,今天在提示下,尝试用脚本直接实现接口,然后c#可以动态或指定新类型创建接口实现对象。从代码角度看,稍显复杂,但脚本方面显得更简洁和有条理。

引用包需要microsoft.codeanalysis、microsoft.codeanalysis.common等,其他自动添加:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="humanizer.core" version="2.14.1" targetframework="net472" />
  <package id="microsoft.bcl.asyncinterfaces" version="8.0.0" targetframework="net472" />
  <package id="microsoft.codeanalysis" version="4.13.0" targetframework="net472" />
  <package id="microsoft.codeanalysis.analyzers" version="3.11.0" targetframework="net472" developmentdependency="true" />
  <package id="microsoft.codeanalysis.common" version="4.13.0" targetframework="net472" />
  <package id="microsoft.codeanalysis.csharp" version="4.13.0" targetframework="net472" />
  <package id="microsoft.codeanalysis.csharp.scripting" version="4.13.0" targetframework="net472" />
  <package id="microsoft.codeanalysis.csharp.workspaces" version="4.13.0" targetframework="net472" />
  <package id="microsoft.codeanalysis.scripting.common" version="4.13.0" targetframework="net472" />
  <package id="microsoft.codeanalysis.visualbasic" version="4.13.0" targetframework="net472" />
  <package id="microsoft.codeanalysis.visualbasic.workspaces" version="4.13.0" targetframework="net472" />
  <package id="microsoft.codeanalysis.workspaces.common" version="4.13.0" targetframework="net472" />
  <package id="microsoft.csharp" version="4.7.0" targetframework="net472" />
  <package id="system.buffers" version="4.5.1" targetframework="net472" />
  <package id="system.collections.immutable" version="8.0.0" targetframework="net472" />
  <package id="system.composition" version="8.0.0" targetframework="net472" />
  <package id="system.composition.attributedmodel" version="8.0.0" targetframework="net472" />
  <package id="system.composition.convention" version="8.0.0" targetframework="net472" />
  <package id="system.composition.hosting" version="8.0.0" targetframework="net472" />
  <package id="system.composition.runtime" version="8.0.0" targetframework="net472" />
  <package id="system.composition.typedparts" version="8.0.0" targetframework="net472" />
  <package id="system.io.pipelines" version="8.0.0" targetframework="net472" />
  <package id="system.memory" version="4.5.5" targetframework="net472" />
  <package id="system.numerics.vectors" version="4.5.0" targetframework="net472" />
  <package id="system.reflection.metadata" version="8.0.0" targetframework="net472" />
  <package id="system.runtime.compilerservices.unsafe" version="6.0.0" targetframework="net472" />
  <package id="system.text.encoding.codepages" version="7.0.0" targetframework="net472" />
  <package id="system.threading.channels" version="7.0.0" targetframework="net472" />
  <package id="system.threading.tasks.extensions" version="4.5.4" targetframework="net472" />
</packages>

接口定义如下:

namespace windowsformsapp1
{
    public interface iflexiblepluginagent
    {
        string registdrtype();
    }
}

验证文件textfile1.txt如下:

using system;
using system.collections.generic;
 
public class flexiblepluginagentprocessscriptxxxx : windowsformsapp1.iflexiblepluginagent
{
	public string registdrtype()
	{
		return "scritp_drv";
	}
}

加载和验证代码如下:

using microsoft.codeanalysis.csharp;
using microsoft.codeanalysis.emit;
using microsoft.codeanalysis;
using system;
using system.collections.generic;
using system.io;
using system.linq;
using system.reflection;
 
namespace windowsformsapp1
{
    internal static class program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [stathread]
        static void main()
        {
            scripttest();
        }
        static void scripttest()
        {
            try
            {
                // 读取外部代码文件
                string codefilepath = "textfile1.txt";
                string sourcecode = file.readalltext(codefilepath);
 
                var compilation = csharpcompilation.create("dynamicassembly")
                    .withoptions(new csharpcompilationoptions(outputkind.dynamicallylinkedlibrary))
                    .addreferences(metadatareference.createfromfile(typeof(object).assembly.location))
                    .addreferences(metadatareference.createfromfile(typeof(iflexiblepluginagent).assembly.location))
                    .addsyntaxtrees(csharpsyntaxtree.parsetext(sourcecode));
 
                // 检查编译错误
                var diagnostics = compilation.getdiagnostics();
                if (diagnostics.hasanyerrors())
                {
                    console.writeline("编译错误:");
                    foreach (var diagnostic in diagnostics.where(d => d.severity == diagnosticseverity.error))
                    {
                        console.writeline(diagnostic.tostring());
                    }
                    return;
                }
 
                // 内存中生成程序集
                using (var ms = new memorystream())
                {
                    emitresult emitresult = compilation.emit(ms);
 
                    if (!emitresult.success)
                    {
                        console.writeline("程序集生成失败:");
                        foreach (var diagnostic in emitresult.diagnostics.where(d => d.severity == diagnosticseverity.error))
                        {
                            console.writeline(diagnostic.tostring());
                        }
                        return;
                    }
 
                    ms.seek(0, seekorigin.begin);
                    assembly assembly = assembly.load(ms.toarray());
 
                    console.writeline("---检查程序集中是否有iflexiblepluginagent的派生类---");
                    var derivedtypes = assembly.definedtypes
                        .where(t => typeof(iflexiblepluginagent).isassignablefrom(t) && !t.isinterface)
                        .tolist();
 
                    if (derivedtypes.any())
                    {
                        console.writeline("找到以下iflexiblepluginagent的派生类:");
                        foreach (var type in derivedtypes)
                        {
                            console.writeline($"  - {type.fullname}");
                        }
 
                        // 使用第一个派生类创建对象
                        type agenttype = derivedtypes.first().astype();
                        iflexiblepluginagent agent = (iflexiblepluginagent)activator.createinstance(agenttype);
                        string result = agent.registdrtype();
 
                        console.writeline($"注册的 drtype 是: {result}");
                    }
                    else
                    {
                        console.writeline("未找到iflexiblepluginagent的派生类");
                    }
 
                    console.writeline("---知道类名字直接调用---");
                    type agenttype2 = assembly.gettype("flexiblepluginagentprocessscriptxxxx");
                    if (agenttype2 == null)
                    {
                        console.writeline("未找到 mypluginagent 类型");
                        return;
                    }
 
                    iflexiblepluginagent agent2 = (iflexiblepluginagent)activator.createinstance(agenttype2);
                    string result2 = agent2.registdrtype();
 
                    console.writeline($"注册的 drtype 是: {result2}");
 
                }
            }
            catch (exception ex)
            {
                console.writeline($"发生错误: {ex.message}");
            }
        }
    }
    // 扩展方法用于检查诊断信息
    public static class diagnosticextensions
    {
        public static bool hasanyerrors(this ienumerable<diagnostic> diagnostics)
        {
            return diagnostics.any(d => d.severity == diagnosticseverity.error);
        }
    }
}

到此这篇关于c#通过脚本实现接口的示例详解的文章就介绍到这了,更多相关c#接口内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

C#中使用YOLO的常用方式的详细指南

05-15

C#特性(Attributes)和反射(Reflection)详解

05-14

基于C#实现MQTT通信实战

05-18

C#实现将超大图片(1GB)裁剪为8张小图片

05-18

利用C#实现访问远程硬盘的高效方案

05-18

基于C#创建高效自定义图像显示控件

05-18

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论