Before Rebuild NetProvider
This commit is contained in:
@@ -5,17 +5,18 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using BITKit.Mod;
|
||||
|
||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
using System.Collections;
|
||||
using BITKit.UX;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using static BITKit.Mod.DotNetSdkRoslynService;
|
||||
#endif
|
||||
#if UNITY_EDITOR
|
||||
@@ -60,170 +61,162 @@ namespace BITKit
|
||||
assemblies ??= AppDomain.CurrentDomain.GetAssemblies();
|
||||
return assemblies.Select(assembly => assembly.GetType(fullName, false)).FirstOrDefault(type => type is not null);
|
||||
}
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
|
||||
public static Assembly Compile(params string[] codes)
|
||||
public static IReadOnlyCollection<Assembly> GetReferencedAssemblies(Type type)
|
||||
{
|
||||
var outputPath = PathHelper.GetTempFilePath();
|
||||
|
||||
try
|
||||
var result = new HashSet<Assembly>();
|
||||
foreach (var fieldInfo in type.GetFields())
|
||||
{
|
||||
if (Installed is false)
|
||||
{
|
||||
throw new FileNotFoundException($"未从当前路径找到Roslyn:\n{CSCPath}");
|
||||
}
|
||||
|
||||
var argumentBuilder = new StringBuilder();
|
||||
|
||||
var tempList = new List<string> { outputPath };
|
||||
|
||||
foreach (var code in codes)
|
||||
{
|
||||
var temp = PathHelper.GetTempFilePath();
|
||||
|
||||
File.WriteAllText(temp,code);
|
||||
|
||||
argumentBuilder.Append(" ");
|
||||
argumentBuilder.Append(temp);
|
||||
|
||||
tempList.Add(temp);
|
||||
}
|
||||
|
||||
argumentBuilder.Append(" -target:library");
|
||||
|
||||
argumentBuilder.Append(" /unsafe");
|
||||
|
||||
foreach (var x in ReferencedAssemblies)
|
||||
{
|
||||
argumentBuilder.Append(" ");
|
||||
argumentBuilder.Append("-r:");
|
||||
argumentBuilder.Append(x);
|
||||
//argumentBuilder.Append(Path.Combine(dllPath, x));
|
||||
}
|
||||
|
||||
argumentBuilder.Append(" ");
|
||||
argumentBuilder.Append($"-out:{outputPath}");
|
||||
|
||||
BIT4Log.Log<BITSharp>("已创建编译参数:");
|
||||
BIT4Log.Log(argumentBuilder.ToString());
|
||||
|
||||
BIT4Log.Log<BITSharp>($"dotnet {CSCPath} {argumentBuilder}");
|
||||
|
||||
//Original
|
||||
// var StartInfo = new ProcessStartInfo
|
||||
// {
|
||||
// //FileName = MCSPath,
|
||||
// FileName = "dotnet",
|
||||
// Arguments =$"{CSCPath} {argumentBuilder}" ,
|
||||
// UseShellExecute = true,
|
||||
// CreateNoWindow = false,
|
||||
// };
|
||||
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
//FileName = MCSPath,
|
||||
FileName = "dotnet",
|
||||
Arguments =$"{CSCPath} {argumentBuilder}" ,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
StandardErrorEncoding = System.Text.Encoding.GetEncoding("gb2312"),
|
||||
StandardInputEncoding = System.Text.Encoding.GetEncoding("gb2312"),
|
||||
StandardOutputEncoding = System.Text.Encoding.GetEncoding("gb2312"),
|
||||
};
|
||||
|
||||
|
||||
var process = new Process()
|
||||
{
|
||||
StartInfo = startInfo,
|
||||
};
|
||||
var reportBuilder = new StringBuilder();
|
||||
process.OutputDataReceived += (sender, args) =>
|
||||
{
|
||||
//BIT4Log.Log<BITSharp>(args.Data);
|
||||
reportBuilder.AppendLine(args.Data);
|
||||
};
|
||||
process.ErrorDataReceived += (sender, args) =>
|
||||
{
|
||||
//BIT4Log.Warning<BITSharp>(args.Data);
|
||||
reportBuilder.AppendLine($"<color=yellow>{args.Data}</color>");
|
||||
};
|
||||
|
||||
process.Start();
|
||||
BIT4Log.Log<BITSharp>("已启动");
|
||||
|
||||
process.BeginErrorReadLine();
|
||||
process.BeginOutputReadLine();
|
||||
result.Add(fieldInfo.FieldType.Assembly);
|
||||
}
|
||||
|
||||
foreach (var propertyInfo in type.GetProperties())
|
||||
{
|
||||
result.Add(propertyInfo.PropertyType.Assembly);
|
||||
}
|
||||
foreach (var methodInfo in type.GetMethods())
|
||||
{
|
||||
result.Add(methodInfo.ReturnType.Assembly);
|
||||
foreach (var argument in methodInfo.GetGenericArguments())
|
||||
{
|
||||
result.Add(argument.Assembly);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string GenerateCodeFromInterface(Type type,string namespaceName = null)
|
||||
{
|
||||
if (type.IsInterface is false) throw new InvalidDataException("The type have to be interface");
|
||||
|
||||
var codeBuilder = new StringBuilder();
|
||||
|
||||
var nameSpaces = new HashSet<string>();
|
||||
|
||||
HashSet<Type> allTypes = new();
|
||||
HashSet<MethodInfo> propertyMethods = new();
|
||||
|
||||
foreach (var propertyInfo in type.GetProperties())
|
||||
{
|
||||
if (propertyInfo.GetMethod is not null)
|
||||
{
|
||||
propertyMethods.Add(propertyInfo.GetMethod);
|
||||
}
|
||||
|
||||
if (propertyInfo.SetMethod is not null)
|
||||
{
|
||||
propertyMethods.Add(propertyInfo.SetMethod);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var method in type.GetMethods())
|
||||
{
|
||||
if (method.DeclaringType is not null)
|
||||
{
|
||||
nameSpaces.Add(method.DeclaringType.Namespace);
|
||||
}
|
||||
nameSpaces.Add(method.ReturnType.Namespace);
|
||||
foreach (var argument in method.GetGenericArguments())
|
||||
{
|
||||
nameSpaces.Add(argument.Namespace);
|
||||
}
|
||||
}
|
||||
|
||||
nameSpaces.Add("System");
|
||||
nameSpaces.Add("System.Collections.Concurrent");
|
||||
nameSpaces.Add("System.Collections.Generic");
|
||||
|
||||
|
||||
while (process.HasExited is false)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
if (BITApp.CancellationToken.IsCancellationRequested) throw new OperationCanceledException("程序已退出,取消编译");
|
||||
}
|
||||
|
||||
var bytes = File.ReadAllBytes(outputPath);
|
||||
|
||||
if(process.ExitCode is not 0)
|
||||
codeBuilder.AppendLine(string.Join('\n', nameSpaces.Select(x=>$"using {x};")));
|
||||
|
||||
|
||||
//codeBuilder.AppendLine("namespace BITSharpGen");
|
||||
//codeBuilder.AppendLine("{");
|
||||
|
||||
codeBuilder.AppendLine($"public class @{type.Name}Gen : {type.Name}");
|
||||
codeBuilder.AppendLine("{");
|
||||
|
||||
|
||||
foreach (var propertyInfo in type.GetProperties())
|
||||
{
|
||||
codeBuilder.AppendLine($"public {CSharpName(propertyInfo.PropertyType)} {propertyInfo.Name}" + "{ get;set; }");
|
||||
}
|
||||
|
||||
// 遍历接口的所有成员,生成方法的默认实现
|
||||
foreach (var method in type.GetMethods())
|
||||
{
|
||||
if(propertyMethods.Contains(method))continue;
|
||||
string methodName = method.Name;
|
||||
string parameters = string.Join(", ", method.GetParameters()
|
||||
.Select(p => $"{CSharpName(p.ParameterType)} {p.Name}"));
|
||||
|
||||
// 检查是否为泛型方法
|
||||
if (method.IsGenericMethod)
|
||||
{
|
||||
// 处理泛型方法
|
||||
var genericArgs = string.Join(", ", method.GetGenericArguments()
|
||||
.Select(arg => CSharpName(arg)));
|
||||
|
||||
if (method.ReturnType == typeof(void))
|
||||
{
|
||||
BIT4Log.LogException(new Exception($"编译失败:{process.ExitCode}"));
|
||||
codeBuilder.AppendLine($" public void {methodName}<{genericArgs}>({parameters}) {{ }}");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var x in tempList)
|
||||
{
|
||||
File.Delete(x);
|
||||
}
|
||||
codeBuilder.AppendLine($" public {CSharpName(method.ReturnType)} {methodName}<{genericArgs}>({parameters}) {{ return default({CSharpName(method.ReturnType)}); }}");
|
||||
}
|
||||
|
||||
BIT4Log.Log<BITSharp>(reportBuilder);
|
||||
|
||||
return Assembly.Load(bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (method.ReturnType == typeof(void))
|
||||
{
|
||||
codeBuilder.AppendLine($" public void {methodName}({parameters}) {{ }}"); // Void 方法默认空实现
|
||||
}
|
||||
else
|
||||
{
|
||||
// 返回默认值
|
||||
codeBuilder.AppendLine($" public {CSharpName(method.ReturnType)} {methodName}({parameters}) {{ return default({CSharpName(method.ReturnType)}); }}");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"编译失败:{e}");
|
||||
}
|
||||
|
||||
// var codeProvider = new CSharpCodeProvider();
|
||||
// var parameters = new CompilerParameters
|
||||
// {
|
||||
// GenerateInMemory = true,
|
||||
// CompilerOptions = "/unsafe",
|
||||
// OutputAssembly = outputPath,
|
||||
// };
|
||||
// parameters.ReferencedAssemblies.Add("System.dll");
|
||||
// foreach (var x in ReferencedAssemblies)
|
||||
// {
|
||||
// parameters.ReferencedAssemblies.Add(x);
|
||||
// BIT4Log.Log<BITSharp>($"添加引用:");
|
||||
// BIT4Log.Log<BITSharp>(x);
|
||||
// }
|
||||
//
|
||||
// BIT4Log.Log<BITSharp>($"程序集输出路径:{outputPath}");
|
||||
//
|
||||
// var results = codeProvider.CompileAssemblyFromSource(parameters, codes);
|
||||
//
|
||||
// if (results.Errors.Count <= 0)
|
||||
// {
|
||||
// BIT4Log.Log<BITSharp>($"编译成功:{results.CompiledAssembly.FullName}");
|
||||
//
|
||||
// codeProvider.Dispose();
|
||||
// return results.CompiledAssembly;
|
||||
// }
|
||||
//
|
||||
// foreach (CompilerError error in results.Errors)
|
||||
// {
|
||||
// var sb = new StringBuilder();
|
||||
// sb.AppendLine(error.FileName);
|
||||
// sb.AppendLine($"Error ({error.ErrorNumber}): {error.ErrorText}");
|
||||
// sb.AppendLine($"Line: {error.Line}, Column: {error.Column}");
|
||||
// sb.AppendLine($"Is Warning: {error.IsWarning}");
|
||||
// BIT4Log.LogException(new Exception(sb.ToString()));
|
||||
// }
|
||||
//
|
||||
// throw new Exception("编译失败");
|
||||
|
||||
|
||||
//codeBuilder.AppendLine("\t}");
|
||||
|
||||
codeBuilder.AppendLine("}");
|
||||
|
||||
return codeBuilder.ToString();
|
||||
}
|
||||
|
||||
public static string CSharpName(Type type)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var name = type.Name;
|
||||
if (!type.IsGenericType) return name;
|
||||
sb.Append(name.Substring(0, name.IndexOf('`')));
|
||||
sb.Append("<");
|
||||
sb.Append(string.Join(", ", type.GetGenericArguments()
|
||||
.Select(t => CSharpName(t))));
|
||||
sb.Append(">");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static Assembly Compile(string code,ScriptOptions scriptOptions=null)
|
||||
{
|
||||
scriptOptions ??= ScriptOptions.Default;
|
||||
|
||||
var script = CSharpScript.Create(code,scriptOptions);
|
||||
script.Compile();
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
var result = script.GetCompilation().Emit(ms);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
var assembly = Assembly.Load(ms.ToArray()); // 加载程序集
|
||||
|
||||
return assembly;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user