C#通過腳本實(shí)現(xiàn)接口的示例詳解
以前C#腳本用的委托注入模式,今天在提示下,嘗試用腳本直接實(shí)現(xiàn)接口,然后C#可以動(dòng)態(tài)或指定新類型創(chuàng)建接口實(shí)現(xiàn)對(duì)象。從代碼角度看,稍顯復(fù)雜,但腳本方面顯得更簡(jiǎn)潔和有條理。
引用包需要Microsoft.CodeAnalysis、Microsoft.CodeAnalysis.Common等,其他自動(dòng)添加:
<?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();
}
}驗(yàn)證文件TextFile1.txt如下:
using System;
using System.Collections.Generic;
public class FlexiblePluginAgentProcessScriptXXXX : WindowsFormsApp1.IFlexiblePluginAgent
{
public string RegistDrType()
{
return "scritp_drv";
}
}加載和驗(yàn)證代碼如下:
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>
/// 應(yīng)用程序的主入口點(diǎn)。
/// </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));
// 檢查編譯錯(cuò)誤
var diagnostics = compilation.GetDiagnostics();
if (diagnostics.HasAnyErrors())
{
Console.WriteLine("編譯錯(cuò)誤:");
foreach (var diagnostic in diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error))
{
Console.WriteLine(diagnostic.ToString());
}
return;
}
// 內(nèi)存中生成程序集
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}");
}
// 使用第一個(gè)派生類創(chuàng)建對(duì)象
Type agentType = derivedTypes.First().AsType();
IFlexiblePluginAgent agent = (IFlexiblePluginAgent)Activator.CreateInstance(agentType);
string result = agent.RegistDrType();
Console.WriteLine($"注冊(cè)的 DrType 是: {result}");
}
else
{
Console.WriteLine("未找到IFlexiblePluginAgent的派生類");
}
Console.WriteLine("---知道類名字直接調(diào)用---");
Type agentType2 = assembly.GetType("FlexiblePluginAgentProcessScriptXXXX");
if (agentType2 == null)
{
Console.WriteLine("未找到 MyPluginAgent 類型");
return;
}
IFlexiblePluginAgent agent2 = (IFlexiblePluginAgent)Activator.CreateInstance(agentType2);
string result2 = agent2.RegistDrType();
Console.WriteLine($"注冊(cè)的 DrType 是: {result2}");
}
}
catch (Exception ex)
{
Console.WriteLine($"發(fā)生錯(cuò)誤: {ex.Message}");
}
}
}
// 擴(kuò)展方法用于檢查診斷信息
public static class DiagnosticExtensions
{
public static bool HasAnyErrors(this IEnumerable<Diagnostic> diagnostics)
{
return diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error);
}
}
}到此這篇關(guān)于C#通過腳本實(shí)現(xiàn)接口的示例詳解的文章就介紹到這了,更多相關(guān)C#接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)壓縮和解壓縮的方法示例【Gzip和Zip方式】
這篇文章主要介紹了C#實(shí)現(xiàn)壓縮和解壓縮的方法,結(jié)合具體實(shí)例形式分析了Gzip和Zip兩種壓縮操作實(shí)現(xiàn)方法,需要的朋友可以參考下2017-06-06
詳解DataGridView控件的數(shù)據(jù)綁定
本文詳細(xì)講解了DataGridView控件的數(shù)據(jù)綁定,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02
C#設(shè)計(jì)模式之ChainOfResponsibility職責(zé)鏈模式解決真假美猴王問題實(shí)例
這篇文章主要介紹了C#設(shè)計(jì)模式之ChainOfResponsibility職責(zé)鏈模式解決真假美猴王問題,簡(jiǎn)單說明了責(zé)任鏈模式的概念,并結(jié)合《西游記》中真假美猴王故事背景為實(shí)例分析了責(zé)任鏈模式的具體使用技巧,需要的朋友可以參考下2017-09-09

