Skip to content

Commit

Permalink
update method builder
Browse files Browse the repository at this point in the history
  • Loading branch information
NMSAzulX committed Jul 9, 2024
1 parent 30737b9 commit 3e5af70
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 126 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Natasha.CSharp.Extension.MethodCreator
{
public class NatashaSlimMethodBuilder
{
public readonly AssemblyCSharpBuilder Builder;
public readonly string Script;
public readonly HashSet<string> Usings;
public object[]? PrivateObjects;
private Action<NatashaLoadContext>? _ctxConfig;
private Action<AssemblyCSharpBuilder>? _builderConfig;
public NatashaSlimMethodBuilder(string script)
{
Usings = [];
Builder = new AssemblyCSharpBuilder();
Script = script;
}
public NatashaSlimMethodBuilder WithPrivateAccess(params object[] objs)
{
PrivateObjects = objs;
return this;
}

public NatashaSlimMethodBuilder ConfigBuilder(Action<AssemblyCSharpBuilder> config)
{
_builderConfig = config;
return this;
}
public NatashaSlimMethodBuilder ConfigBuilder(Action<NatashaLoadContext> config)
{
_ctxConfig = config;
return this;
}
public NatashaSlimMethodBuilder WithSimpleBuilder()
{
Builder.UseRandomLoadContext();
Builder.UseSimpleMode();
Builder.ConfigLoadContext(ctx => ctx.AddReferenceAndUsingCode<object>());
return this;
}

public NatashaSlimMethodBuilder WithUsings(params string[] usings)
{
Usings.UnionWith(usings);
return this;
}

public NatashaSlimMethodBuilder WithMetadata<T>()
{
Builder.ConfigLoadContext(ctx => ctx.AddReferenceAndUsingCode<T>());
return this;
}

public NatashaSlimMethodBuilder WithMetadata(params Type[] types)
{
if (types!=null && types.Length == 0)
{
foreach (var type in types)
{
Builder.ConfigLoadContext(ctx => ctx.AddReferenceAndUsingCode(type));
}
}
return this;
}

public T ToDelegate<T>(string modifier = "") where T : Delegate
{
_builderConfig?.Invoke(Builder);
_ctxConfig?.Invoke(Builder.LoadContext);

var className = $"N{Guid.NewGuid():N}";
var methodInfo = typeof(T).GetMethod("Invoke")!;

var returnTypeScript = methodInfo.ReturnType.GetDevelopName();
var parameterScript = new StringBuilder();

var methodParameters = methodInfo.GetParameters();
for (int i = 0; i < methodParameters.Length; i += 1)
{
var paramType = methodParameters[i].ParameterType;
Builder.ConfigLoadContext(ctx => ctx.AddReferenceAndUsingCode(paramType));
parameterScript.Append($"{paramType.GetDevelopName()} arg{i + 1},");
}
if (parameterScript.Length > 0)
{
parameterScript.Length -= 1;
}

StringBuilder usingCode = new();
foreach (var item in Usings)
{

usingCode.AppendLine($"using {item};");

}
var fullScript = $"{usingCode} public static class {className} {{ public static {(modifier ?? string.Empty)} {returnTypeScript} Invoke({parameterScript}){{ {Script} }} }}";
if (PrivateObjects!=null)
{
Builder.Add(fullScript.ToAccessPrivateTree(PrivateObjects));
}
else
{
Builder.Add(fullScript);
}
var asm = Builder.GetAssembly();
var type = asm.GetType(className);
if (type != null)
{
return (T)Delegate.CreateDelegate(typeof(T), type.GetMethod("Invoke")!);
}
throw new Exception($"未找到 {className} 类型!");
}
public T ToAsyncDelegate<T>() where T : Delegate
{
return ToDelegate<T>("async");
}
public T ToUnsafeDelegate<T>() where T : Delegate
{
return ToDelegate<T>("unsafe");
}
public T ToUnsafeAsyncDelegate<T>() where T : Delegate
{
return ToDelegate<T>("unsafe async");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,95 +1,31 @@
using System;
using Natasha.CSharp.Extension.MethodCreator;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

public static class StringExtension
{

public static (string script, string[] usings, AssemblyCSharpBuilder builder) WithAssemblyBuilder(this string script, Func<AssemblyCSharpBuilder, AssemblyCSharpBuilder> config)
public static NatashaSlimMethodBuilder WithSlimMethodBuilder(this string script, Action<AssemblyCSharpBuilder> config)
{
AssemblyCSharpBuilder builder = new();
config?.Invoke(builder);
return (script, [], builder);
var builder = new NatashaSlimMethodBuilder(script);
builder.ConfigBuilder(config);
return builder;
}


public static (string script, string[] usings, AssemblyCSharpBuilder builder) WithAssemblyBuilder(this string script, Func<NatashaLoadContext, NatashaLoadContext> config)
{
AssemblyCSharpBuilder builder = new();
builder.ConfigLoadContext(config);
return (script, [], builder);
}

public static (string script, string[] usings, AssemblyCSharpBuilder builder) WithSimpleBuilder(this string script)
{
AssemblyCSharpBuilder builder = new();
builder.UseRandomLoadContext();
builder.UseSimpleMode();
builder.ConfigLoadContext(ctx => ctx.AddReferenceAndUsingCode<object>());
return (script, [], builder);
}

public static (string script, string[] usings, AssemblyCSharpBuilder builder) WithMetadata<T>(in this (string script, string[] usings, AssemblyCSharpBuilder builder) buildInfo)
{
return (buildInfo.script, buildInfo.usings, buildInfo.builder.ConfigLoadContext(ctx => ctx.AddReferenceAndUsingCode(typeof(T))));
}
public static (string script, string[] usings, AssemblyCSharpBuilder builder) WithMetadata(in this (string script, string[] usings, AssemblyCSharpBuilder builder) buildInfo, Type type)
public static NatashaSlimMethodBuilder WithSlimMethodBuilder(this string script, Action<NatashaLoadContext> config)
{
return (buildInfo.script, buildInfo.usings, buildInfo.builder.ConfigLoadContext(ctx => ctx.AddReferenceAndUsingCode(type)));
var builder = new NatashaSlimMethodBuilder(script);
builder.ConfigBuilder(config);
return builder;
}
public static (string script, string[] usings, AssemblyCSharpBuilder builder) WithUsings(in this (string script, string[] usings, AssemblyCSharpBuilder builder) buildInfo,params string[] usings)
{
return (buildInfo.script, usings, buildInfo.builder);
}
public static T ToDelegate<T>(in this (string script, string[] usings, AssemblyCSharpBuilder builder) buildInfo, string modifier = "") where T: Delegate
{
var scriptBuilder = buildInfo.builder;
var className = $"N{Guid.NewGuid():N}";
var methodInfo = typeof(T).GetMethod("Invoke")!;

var returnTypeScript = methodInfo.ReturnType.GetDevelopName();
var parameterScript = new StringBuilder();

var methodParameters = methodInfo.GetParameters();
for (int i = 0; i < methodParameters.Length; i+=1)
{
var paramType = methodParameters[i].ParameterType;
scriptBuilder.ConfigLoadContext(ctx => ctx.AddReferenceAndUsingCode(paramType));
parameterScript.Append($"{paramType.GetDevelopName()} arg{i+1},");
}
if (parameterScript.Length > 0)
{
parameterScript.Length -= 1;
}

StringBuilder usingCode = new();
foreach (var item in buildInfo.usings)
{

usingCode.AppendLine($"using {item};");

}
buildInfo.builder.Add($"{usingCode} public static class {className} {{ public static {(modifier ?? string.Empty)} {returnTypeScript} Invoke({parameterScript}){{ {buildInfo.script} }} }}");
var asm = buildInfo.builder.GetAssembly();
var type = asm.GetType(className);
if (type != null)
{
return (T)Delegate.CreateDelegate(typeof(T), type.GetMethod("Invoke")!);
}
throw new Exception($"未找到 {className} 类型!");
}
public static T ToAsyncDelegate<T>(in this (string script, string[] usings, AssemblyCSharpBuilder builder) buildInfo) where T : Delegate
{
return ToDelegate<T>(buildInfo, "async");
}
public static T ToUnsafeDelegate<T>(in this (string script, string[] usings, AssemblyCSharpBuilder builder) buildInfo) where T : Delegate
{
return ToDelegate<T>(buildInfo, "unsafe");
}
public static T ToUnsafeAsyncDelegate<T>(in this (string script, string[] usings, AssemblyCSharpBuilder builder) buildInfo) where T : Delegate
public static NatashaSlimMethodBuilder WithSlimMethodBuilder(this string script)
{
return ToDelegate<T>(buildInfo, "unsafe async");
var builder = new NatashaSlimMethodBuilder(script);
builder.WithSimpleBuilder();
return builder;
}
}

Loading

0 comments on commit 3e5af70

Please sign in to comment.