BITFALL/Assets/BITKit/Core/Sharp/BITSharp.cs

206 lines
7.0 KiB
C#
Raw Normal View History

2023-08-12 01:43:24 +08:00
using System;
2024-01-27 04:09:57 +08:00
using System.CodeDom.Compiler;
2023-08-12 01:43:24 +08:00
using System.Collections.Concurrent;
2024-01-27 04:09:57 +08:00
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
2023-08-12 01:43:24 +08:00
using System.Reflection;
2024-01-27 04:09:57 +08:00
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using BITKit.Mod;
using Microsoft.CSharp;
#if UNITY_64
using static BITKit.Mod.MonoBleedingEdgeService;
#endif
2023-08-12 01:43:24 +08:00
namespace BITKit
{
public class BITSharp
{
2024-01-27 04:09:57 +08:00
public static readonly List<string> ReferencedAssemblies = new();
2023-08-12 01:43:24 +08:00
private static readonly ConcurrentDictionary<string, Type> Dictionary = new();
2024-01-27 04:09:57 +08:00
private static Assembly[] assemblies;
public static bool TryGetTypeFromFullName(string fullClassName, out Type type)
2023-08-12 01:43:24 +08:00
{
type = GetTypeFromFullName(fullClassName);
return type is not null ? true : false;
}
2024-01-27 04:09:57 +08:00
2023-08-12 01:43:24 +08:00
public static Type GetTypeFromFullName(string fullClassName)
{
return Dictionary.GetOrAdd(fullClassName, SearchType);
}
2024-01-27 04:09:57 +08:00
private static Type SearchType(string fullName)
2023-08-12 01:43:24 +08:00
{
2024-01-27 04:09:57 +08:00
assemblies = assemblies ?? AppDomain.CurrentDomain.GetAssemblies();
2023-08-12 01:43:24 +08:00
foreach (var assembly in assemblies)
{
2024-01-27 04:09:57 +08:00
var type = assembly.GetType(fullName, false);
2023-08-12 01:43:24 +08:00
if (type is not null)
{
2024-01-27 04:09:57 +08:00
return type;
2023-08-12 01:43:24 +08:00
}
else
{
continue;
}
}
2024-01-27 04:09:57 +08:00
2023-08-12 01:43:24 +08:00
return null;
}
2024-01-27 04:09:57 +08:00
#if UNITY_64
public static Assembly Compile(params string[] codes)
{
var outputPath = PathHelper.GetTempFilePath();
try
{
if (MonoBleedingEdgeService.Installed is false)
{
throw new FileNotFoundException($"未从当前路径找到mcs:\n{MCSPath}");
}
var argumentBuilder = new StringBuilder();
var dllPath = Assembly.GetExecutingAssembly().Location;
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(" ");
argumentBuilder.Append("-target:library");
// foreach (var fileInfo in new FileInfo(Assembly.GetExecutingAssembly()!.Location!).Directory!.GetFiles())
// {
// if(fileInfo.Extension is not ".dll")continue;
//
// argumentBuilder.Append(" ");
// argumentBuilder.Append("-r:");
// argumentBuilder.Append(fileInfo.FullName);
// }
foreach (var x in ReferencedAssemblies)
{
argumentBuilder.Append(" ");
argumentBuilder.Append("-r:");
argumentBuilder.Append(Path.Combine(dllPath, x));
}
argumentBuilder.Append(" ");
argumentBuilder.Append($"-out:{outputPath}");
BIT4Log.Log<BITSharp>("已创建编译参数:");
BIT4Log.Log(argumentBuilder.ToString());
var StartInfo = new ProcessStartInfo
{
FileName = MCSPath,
Arguments = argumentBuilder.ToString(),
UseShellExecute = true,
CreateNoWindow = false,
};
var process = new Process()
{
StartInfo = StartInfo,
};
process.OutputDataReceived += (sender, args) =>
{
BIT4Log.Log<BITSharp>(args.Data);
};
process.ErrorDataReceived += (sender, args) =>
{
BIT4Log.Warning<BITSharp>(args.Data);
};
//var exited=false;
process.Start();
BIT4Log.Log<BITSharp>("已启动");
process.WaitForExit();
// process.Exited += (sender, args) =>
// {
// exited = true;
// BIT4Log.Log<BITSharp>("已退出");
// };
// BIT4Log.Log<BITSharp>("完成");
//
// while (exited is false && process.HasExited is false)
// {
// Thread.Sleep(100);
// }
var bytes = File.ReadAllBytes(outputPath);
foreach (var x in tempList)
{
File.Delete(x);
}
return Assembly.Load(bytes);
}
catch (Exception e)
{
throw new Exception($"编译失败:{e}");
}
// if (BITAppForUnity.IsEditor)
// {
//
// }
// else
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("编译失败");
}
#endif
2023-08-12 01:43:24 +08:00
}
}