繼上一篇《與下位機或設備的通訊解析優化的一點功能:T4+動態編譯》 ,如今已經生成出解析用的類的C#源碼了,接下來,就輪到動態編譯生成Type了。html
在實現上,。net framework和。net core上,有些不一樣:框架
.Net Framework的:dom
1 var transfer = ""; //解析後的C#源碼字符串 2 3 ICodeCompiler comp = new CSharpCodeProvider().CreateCompiler(); 4 5 //編譯器的傳入參數 6 CompilerParameters cp = new CompilerParameters(); 7 8 //引入對應的dll 9 cp.ReferencedAssemblies.Add("system.dll"); //添加程序集 system.dll 的引用 10 cp.ReferencedAssemblies.Add("system.data.dll"); //添加程序集 system.data.dll 的引用 11 cp.ReferencedAssemblies.Add("system.xml.dll"); //添加程序集 system.xml.dll 的引用 12 cp.ReferencedAssemblies.Add("Kugar.Core.dll"); 13 cp.ReferencedAssemblies.Add("Newtonsoft.Json.dll"); 14 cp.ReferencedAssemblies.Add("Kugar.GPS.Api.Data.dll"); 15 cp.ReferencedAssemblies.Add("Kugar.GPS.Api.BLL.dll"); 16 cp.ReferencedAssemblies.Add("MongoDB.Bson.dll"); 17 cp.ReferencedAssemblies.Add("MongoDB.Driver.Core.dll"); 18 19 cp.GenerateExecutable = false; //不生成可執行文件 20 cp.GenerateInMemory = true; //在內存中運行 21 cp.IncludeDebugInformation = false; 22 23 CompilerResults results = comp.CompileAssemblyFromSource(cp, transfer); 24 25 if (results.Errors.HasErrors) 26 { 27 foreach (CompilerError error in results.Errors) 28 { 29 LoggerManager.Default.Debug("生成類出錯:" + error.ErrorText); 30 } 31 32 return null; 33 } 34 35 //獲取生成後的應用程序集中,對應的類Type 36 var type = results.CompiledAssembly.GetTypes() 37 .Where(x => x.IsImplementlInterface(typeof(IProtocolExecutor))).FirstOrDefault(); 38 39 return (IProtocolExecutor) Activator.CreateInstance(type, newProtocol.ProtocolID,newProtocol.Version); //實例化解析類
.Net Core 下的:ide
Nuget下安裝 System.Runtime.Loader,System.CodeDom,Microsoft.CodeAnalysis.CSharp包優化
1 var transfer = ""; //T4生成出來的C#源碼 2 3 SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(transfer); 4 5 6 string assemblyName = Path.GetRandomFileName(); 7 MetadataReference[] references = null; 8 9 try 10 { 11 //添加當前應用程序域裏全部的dll引用 12 references = DependencyContext.Default 13 .CompileLibraries 14 .SelectMany(x => x.ResolveReferencePaths(new ReferenceAssemblyPathResolver())) 15 .Where(path => !string.IsNullOrWhiteSpace(path)) 16 .Select(path => MetadataReference.CreateFromFile(path)).ToArrayEx(); 17 18 19 } 20 catch (Exception e) 21 { 22 Console.WriteLine(e); 23 throw; 24 } 25 26 CSharpCompilation compilation = CSharpCompilation.Create( 27 assemblyName, 28 syntaxTrees: new[] { syntaxTree }, 29 references: references, 30 options:new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) 31 ); 32 33 using (var ms = new MemoryStream()) 34 { 35 EmitResult result = compilation.Emit(ms); 36 37 if (!result.Success) 38 { 39 IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic => 40 diagnostic.IsWarningAsError || 41 diagnostic.Severity == DiagnosticSeverity.Error); 42 43 foreach (Diagnostic diagnostic in failures) 44 { 45 Console.Error.WriteLine("\t{0}: {1}", diagnostic.Id, diagnostic.GetMessage()); 46 } 47 48 return null; 49 } 50 else 51 { 52 ms.Seek(0, SeekOrigin.Begin); 53 54 Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms); 55 56 var type = assembly.GetTypes() 57 .Where(x => x.IsImplementlInterface(typeof(IProtocolExecutor))).FirstOrDefault(); 58 59 return (IProtocolExecutor)Activator.CreateInstance(type, newProtocol.ProtocolID, newProtocol.Version); //實例化解析類 60 61 } 62 }
兩種框架下的生成稍微有點不一樣,列出來,,複製粘貼一下,,改一改就能夠用上去了spa