Skip to content

Commit

Permalink
重构 插件系统
Browse files Browse the repository at this point in the history
  • Loading branch information
MakesYT committed Jul 21, 2024
1 parent 0e75a26 commit c95882b
Show file tree
Hide file tree
Showing 16 changed files with 243 additions and 47 deletions.
62 changes: 62 additions & 0 deletions Core/JsonCtrs/ScenarioMethodAttributeJsonCtr.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using PluginCore.Attribute;

namespace Core.SDKs.Services.Config;

public class ScenarioMethodAttributeJsonCtr : JsonConverter<ScenarioMethodAttribute>
{
public override ScenarioMethodAttribute? Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
// 创建一个 ScenarioMethodAttribute 实例
ScenarioMethodAttribute attribute = new ScenarioMethodAttribute();

// 确保 JSON 数据以对象开始
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}

// 读取 JSON 对象的属性
while (reader.Read())
{
// 检查是否已经到达对象的结尾
if (reader.TokenType == JsonTokenType.EndObject)
{
return attribute;
}

// 读取属性名称
string propertyName = reader.GetString();
reader.Read(); // 进入属性值

// 根据属性名称将值分配给属性
switch (propertyName)
{
case "Name":
attribute.Name = reader.GetString();
break;
case "ParameterName":
attribute.ParameterName =
JsonSerializer.Deserialize<Dictionary<string, string>>(ref reader, options);
break;
default:
// 跳过未处理的属性
reader.Skip();
break;
}
}

return attribute;
}

public override void Write(Utf8JsonWriter writer, ScenarioMethodAttribute value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteString("Name", value.Name);
writer.WritePropertyName("ParameterName");
JsonSerializer.Serialize(writer, value.ParameterName, value.ParameterName.GetType(), options);
writer.WriteEndObject();
}
}
36 changes: 36 additions & 0 deletions Core/JsonCtrs/ScenarioMethodJsonCtr.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Core.SDKs.CustomScenario;
using Core.SDKs.Services.Plugin;

namespace Core.SDKs.Services.Config;

public class ScenarioMethodJsonCtr : JsonConverter<ScenarioMethod>
{
public override ScenarioMethod? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Console.WriteLine("OnDeserializing");


ScenarioMethod scenario = JsonSerializer.Deserialize<ScenarioMethod>(ref reader, options);
if (scenario.IsFromPlugin)
{
scenario.ServiceProvider = PluginManager.EnablePlugin[scenario.PluginInfo.ToPlgString()].ServiceProvider;
scenario.Method = PluginManager.EnablePlugin[scenario.PluginInfo.ToPlgString()]
.GetMethod(scenario._methodAbsolutelyName);
}

return scenario;
}

public override void Write(Utf8JsonWriter writer, ScenarioMethod value, JsonSerializerOptions options)
{
Console.WriteLine("OnSerializing");

// Don't pass in options when recursively calling Serialize.
JsonSerializer.Serialize(writer, value, options);

// Place "after" code here (OnSerialized)
Console.WriteLine("OnSerialized");
}
}
6 changes: 5 additions & 1 deletion Core/JsonCtrs/TypeJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ public override bool CanConvert(Type objectType)
public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options)
{
var type = (Type)value;
var plugin = PluginManager.EnablePlugin.FirstOrDefault((e) => e.Value._dll == type.Assembly).Value;
if (type.FullName.Contains("Native.KeyCode"))
{
}

var plugin = PluginManager.EnablePlugin.FirstOrDefault((e) => e.Value.IsPluginAssembly(type.Assembly)).Value;
// type.Assembly.
// var a = PluginManager.GetPlugnNameByTypeName(type.FullName);
if (plugin is null)
Expand Down
7 changes: 6 additions & 1 deletion Core/SDKs/CustomScenario/ConnectorItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ public partial class ConnectorItem : ObservableRecipient, IConnectorItem
[ObservableProperty]
private Point _anchor;

[ObservableProperty] private object? _inputObject; //数据
#pragma warning disable CS0657 // Not a valid attribute location for this declaration
[property: JsonConverter(typeof(ObjectJsonConverter))]
[JsonIgnore]
#pragma warning restore CS0657 // Not a valid attribute location for this declaration
[ObservableProperty]
private object? _inputObject; //数据

[ObservableProperty] private bool _isConnected;
[ObservableProperty] private bool _isNotUsed = false;
Expand Down
18 changes: 14 additions & 4 deletions Core/SDKs/CustomScenario/ScenarioMethod.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Collections.ObjectModel;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using Core.SDKs.Services.Config;
using Core.SDKs.Services.Plugin;
using Core.SDKs.Tools;
using PluginCore;
Expand Down Expand Up @@ -31,17 +33,21 @@ public ScenarioMethod(ScenarioMethodType type)
}


public IServiceProvider ServiceProvider { get; set; }
[JsonIgnore] public IServiceProvider ServiceProvider { get; set; }
public bool IsFromPlugin => PluginInfo is not null;

public ScenarioMethodType Type { get; }
public ScenarioMethodType Type { get; set; }

//某些特殊的类型需要存储一定的数据,例如(变量读取/设置 需要对应的变量名)
public object TypeDate { get; set; }
public MethodInfo Method { get; set; }
[JsonIgnore] public MethodInfo Method { get; set; }
public PluginInfo? PluginInfo { get; set; }

[JsonConverter(typeof(ScenarioMethodAttributeJsonCtr))]
public ScenarioMethodAttribute Attribute { get; set; }

public string _methodAbsolutelyName;

public string MethodAbsolutelyName
{
get
Expand Down Expand Up @@ -69,11 +75,15 @@ public string MethodAbsolutelyName
}

sb.Remove(sb.Length - 1, 1);
return $"{PluginInfo.Author}_{PluginInfo.PluginId}#{Method.DeclaringType!.FullName}#{Method.Name}{sb}";
var methodAbsolutelyName =
$"{PluginInfo.Author}_{PluginInfo.PluginId}#{Method.DeclaringType!.FullName}#{Method.Name}{sb}";
_methodAbsolutelyName = methodAbsolutelyName;
return methodAbsolutelyName;
}

return Type.ToString();
}
set { _methodAbsolutelyName = value; }
}


Expand Down
21 changes: 20 additions & 1 deletion Core/SDKs/CustomScenario/ScenarioMethodCategoryGroup.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Core.SDKs.Tools;
using PluginCore.Attribute.Scenario;

namespace Core.SDKs.CustomScenario;

public class ScenarioMethodCategoryGroup
public class ScenarioMethodCategoryGroup : INotifyPropertyChanged
{
public static ScenarioMethodCategoryGroup RootScenarioMethodCategoryGroup = GenBaseScenarioMethodCategoryGroup();

Expand Down Expand Up @@ -161,6 +163,23 @@ public void RemoveMethodsByPluginName(string pluginName)

nowScenarioMethodCategoryGroup.Methods.Remove(target.Last());
}

OnPropertyChanged(nameof(ScenarioMethodCategoryGroup));
}

public event PropertyChangedEventHandler? PropertyChanged;

public virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}

Expand Down
1 change: 1 addition & 0 deletions Core/SDKs/CustomScenario/ScenarioMethodNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public partial class ScenarioMethodNode : ObservableRecipient
[ObservableProperty] private ObservableCollection<ConnectorItem> output = new();
[ObservableProperty] private s节点状态 status = s节点状态.未验证;

[JsonConverter(typeof(ScenarioMethodJsonCtr))]
public ScenarioMethod ScenarioMethod { get; set; }

public bool Invoke(CancellationToken cancellationToken, ObservableCollection<ConnectionItem> connections,
Expand Down
49 changes: 27 additions & 22 deletions Core/SDKs/Services/Config/ConfigManger.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#region

using System.Reflection;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Unicode;
using CommunityToolkit.Mvvm.Messaging;
using Core.SDKs.HotKey;
using Core.ViewModel;
Expand All @@ -27,7 +29,8 @@ public static class ConfigManger
IncludeFields = true,
WriteIndented = true,
ReferenceHandler = ReferenceHandler.Preserve,
Converters = { new ObjectJsonConverter() }
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),

// DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

Expand Down Expand Up @@ -62,31 +65,33 @@ public static void Init()
}

Config.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.Public)
.ToList()
.ForEach(x => {
if (x.GetCustomAttribute<ConfigField>() is { } configField)
{
if (configField.FieldType == ConfigFieldType.快捷键)
{
HotKeyManager.HotKeys.Add(x.GetValue(Config) as HotKeyModel);
}
}
});
Config.ConfigChanged += (sender, args) => {
.GetFields(BindingFlags.Instance | BindingFlags.Public)
.ToList()
.ForEach(x =>
{
if (x.GetCustomAttribute<ConfigField>() is { } configField)
{
if (configField.FieldType == ConfigFieldType.快捷键)
{
HotKeyManager.HotKeys.Add(x.GetValue(Config) as HotKeyModel);
}
}
});
Config.ConfigChanged += (sender, args) =>
{
switch (args.Name)
{
case "autoStart":
{
ServiceManager.Services.GetService<IAutoStartService>()
.ChangeAutoStart(args.Value as bool? ?? false);
.ChangeAutoStart(args.Value as bool? ?? false);
break;
}
case "autoStartEverything":
{
((SearchWindowViewModel)ServiceManager.Services.GetService(typeof(SearchWindowViewModel)))
.EverythingIsOk =
.EverythingIsOk =
!(bool)args.Value;
break;
}
Expand All @@ -97,23 +102,23 @@ public static void Init()
case ThemeEnum.跟随系统:
{
ServiceManager.Services.GetService<IThemeChange>()
.followSys(true);
.followSys(true);
break;
}
case ThemeEnum.深色:
{
ServiceManager.Services.GetService<IThemeChange>()
.followSys(false);
.followSys(false);
ServiceManager.Services.GetService<IThemeChange>()
.changeTo("theme_dark");
.changeTo("theme_dark");
break;
}
case ThemeEnum.浅色:
{
ServiceManager.Services.GetService<IThemeChange>()
.followSys(false);
.followSys(false);
ServiceManager.Services.GetService<IThemeChange>()
.changeTo("theme_light");
.changeTo("theme_light");
break;
}
}
Expand All @@ -129,8 +134,8 @@ public static void RemoveConfig(string key)
foreach (var (s, value) in ConfigManger.Configs.Where(x => x.Key.StartsWith(key)))
{
value.GetType()
.BaseType.GetField("Instance")
.SetValue(value, null);
.BaseType.GetField("Instance")
.SetValue(value, null);
ConfigManger.Configs.Remove(s);
}
}
Expand Down
19 changes: 11 additions & 8 deletions Core/SDKs/Services/Plugin/AssemblyLoadContextH.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

using System.Reflection;
using System.Runtime.Loader;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Unicode;
using Avalonia;
using Core.SDKs.Services.Config;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -22,26 +24,27 @@ public AssemblyLoadContextH(string pluginPath, string name) : base(isCollectible
_resolver = new AssemblyDependencyResolver(pluginPath);
_assembly = this.LoadFromAssemblyPath(pluginPath);

Unloading += (sender) => {
Unloading += (sender) =>
{
AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(x => x.GetName()
.Name == "System.Text.Json")
?.GetType("System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor")
?.GetMethod("Clear")
?.Invoke(null, null);
.FirstOrDefault(x => x.GetName()
.Name == "System.Text.Json")
?.GetType("System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor")
?.GetMethod("Clear")
?.Invoke(null, null);
// var fieldInfo = ConfigManger.DefaultOptions.GetType().GetField("_cachingContext", BindingFlags.NonPublic | BindingFlags.Instance);
// fieldInfo.FieldType.GetMethod("Clear")?.Invoke(fieldInfo.GetValue(ConfigManger.DefaultOptions), null);
ConfigManger.DefaultOptions = new JsonSerializerOptions
{
IncludeFields = true,
WriteIndented = true,
ReferenceHandler = ReferenceHandler.Preserve,
Converters = { new ObjectJsonConverter() }
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
//DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
_assembly = null;
AvaloniaPropertyRegistry.Instance.UnregisterByModule(sender.Assemblies.First()
.DefinedTypes);
.DefinedTypes);
ServiceManager.Services.GetService<IPluginToolService>()!.RequestUninstallPlugin(pluginPath);
};
}
Expand Down
Loading

0 comments on commit c95882b

Please sign in to comment.