Skip to content

Commit f5f179d

Browse files
committed
1. 修复卸载 addin 报错问题
2. 支持三种测试在一个类中混合使用 3. 将传入参数全部转化成字符串 4. 关闭重载插件时检查 hash 值
1 parent db2bfa7 commit f5f179d

17 files changed

+134
-100
lines changed

MSAddinTest/Core/Command/RunPluginCommand.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ namespace MSAddinTest.Core.Command
1616
/// </summary>
1717
internal class RunPluginCommand : CommandBase
1818
{
19-
private IMSTestArg _args;
2019
private string _executorName;
2120

2221
/// <summary>
@@ -26,8 +25,7 @@ internal class RunPluginCommand : CommandBase
2625
/// <param name="args"></param>
2726
public RunPluginCommand(string excutorName)
2827
{
29-
_executorName = excutorName;
30-
_args = new MSTestArg();
28+
_executorName = excutorName;
3129
}
3230

3331
/// <summary>
@@ -44,7 +42,7 @@ public override FuncResult Start()
4442
{
4543
foreach (var kv in PluginContainer)
4644
{
47-
var result = kv.Value.Execute(_executorName, _args);
45+
var result = kv.Value.Execute(_executorName);
4846
if (result.Data is int count) executorsCount += count;
4947
}
5048
}

MSAddinTest/Core/Executor/AddinExecutor.cs

+4-5
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,21 @@ namespace MSAddinTest.Core.Executor
1010
{
1111
internal class AddinExecutor : StaticMethodExecutor
1212
{
13+
public override int Priority { get; } = 100;
14+
1315
public AddinExecutor(Type type, string methodName) : base(type, methodName)
1416
{
1517
Description = "Keyin";
1618
}
1719

18-
public override void Execute(IMSTestArg pluginArg)
20+
public override void Execute(string arg)
1921
{
2022
if (MethodInfo == null) return;
2123

2224
// 调用静态方法
2325
try
2426
{
25-
string unparsedParams = string.Empty;
26-
if (pluginArg is MSTestArg arg) unparsedParams = arg.UnparsedParams;
27-
28-
MethodInfo.Invoke(null, new object[] { unparsedParams });
27+
MethodInfo.Invoke(null, new object[] { arg });
2928
}
3029
catch (Exception ex)
3130
{

MSAddinTest/Core/Executor/ClassExecutor.cs

+15-2
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,26 @@ public ClassExecutor(Type type) : base(type)
2929
}
3030
}
3131

32-
public override void Execute(IMSTestArg pluginArg)
32+
public override void Execute(string arg)
3333
{
3434
var instance = Activator.CreateInstance(Type, BindingFlags.Public | BindingFlags.NonPublic);
3535
if (instance is IMSTest_Class plugin)
3636
{
37-
plugin.Execute(pluginArg);
37+
plugin.Execute(arg);
3838
}
3939
}
40+
41+
/// <summary>
42+
/// 对于类执行器,与静态执行器不冲突
43+
/// 只要不是类执行器,都返回false
44+
/// </summary>
45+
/// <param name="executor"></param>
46+
/// <returns></returns>
47+
public override bool IsSame(ExecutorBase executor)
48+
{
49+
if (!(executor is ClassExecutor))return false;
50+
51+
return base.IsSame(executor);
52+
}
4053
}
4154
}

MSAddinTest/Core/Executor/ExecutorBase.cs

+26-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Linq;
55
using System.Text;
6+
using System.Text.RegularExpressions;
67
using System.Threading.Tasks;
78

89
namespace MSAddinTest.Core.Executor
@@ -12,6 +13,12 @@ namespace MSAddinTest.Core.Executor
1213
/// </summary>
1314
public abstract class ExecutorBase : MarshalByRefObject
1415
{
16+
/// <summary>
17+
/// 优先级
18+
/// 如果重名,则取优先级高的执行器
19+
/// </summary>
20+
public virtual int Priority { get; }
21+
1522
public ExecutorBase(Type type)
1623
{
1724
Type = type;
@@ -34,7 +41,7 @@ public ExecutorBase(Type type)
3441
/// </summary>
3542
public string Description { get; set; }
3643

37-
public abstract void Execute(IMSTestArg plugin);
44+
public abstract void Execute(string arg);
3845

3946
/// <summary>
4047
/// 通过输入字符串匹配当前执行器
@@ -43,16 +50,31 @@ public ExecutorBase(Type type)
4350
/// <param name="name"></param>
4451
/// <param name="args"></param>
4552
/// <returns></returns>
46-
public bool IsMatch(string inputStr, out string name,out string args)
53+
public bool IsMatch(string inputStr, out string name, out string args)
4754
{
4855
args = inputStr;
49-
name = Names.Find(x=>inputStr.ToLower().StartsWith(x.ToLower()));
56+
name = Names.Find(x => inputStr.ToLower().StartsWith(x.ToLower()));
5057
if (name == null) return false;
5158

5259
// 生成参数
53-
args = inputStr.Substring(inputStr.IndexOf(name) + 1);
60+
args = inputStr.Substring(inputStr.ToLower().IndexOf(name.ToLower()) + name.Length).Trim();
5461

5562
return true;
5663
}
64+
65+
/// <summary>
66+
/// 是否是相同命令
67+
/// 只要有一个名称相同,就说明是同一个命令
68+
/// </summary>
69+
/// <param name="obj"></param>
70+
/// <returns></returns>
71+
public virtual bool IsSame(ExecutorBase executor)
72+
{
73+
if (executor == null) return false;
74+
75+
if (executor.Type.FullName != Type.FullName) return false;
76+
77+
return Names.Union(executor.Names).Count() > 0;
78+
}
5779
}
5880
}

MSAddinTest/Core/Executor/StaticMethodExecutor.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace MSAddinTest.Core.Executor
1414
/// </summary>
1515
internal class StaticMethodExecutor : ExecutorBase
1616
{
17+
public override int Priority { get; } = 50;
18+
1719
protected MethodInfo MethodInfo { get; private set; }
1820
public StaticMethodExecutor(MethodInfo methodInfo) : base(null)
1921
{
@@ -45,14 +47,14 @@ private void SetMthodInfo(MethodInfo methodInfo)
4547
}
4648
}
4749

48-
public override void Execute(IMSTestArg plugin)
50+
public override void Execute(string arg)
4951
{
5052
if (MethodInfo == null) return;
5153

5254
// 调用静态方法
5355
try
5456
{
55-
MethodInfo.Invoke(null, new object[] { plugin });
57+
MethodInfo.Invoke(null, new object[] { arg });
5658

5759
}
5860
catch (Exception ex)

MSAddinTest/Core/Loader/AutoReloader.cs

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
using System;
1+
using Bentley.MstnPlatformNET;
2+
using System;
23
using System.Collections.Generic;
34
using System.IO;
45
using System.Linq;
56
using System.Text;
67
using System.Threading.Tasks;
8+
using System.Windows;
79

810
namespace MSAddinTest.Core.Loader
911
{
@@ -42,12 +44,17 @@ public AutoReloader(PluginAssemblyLoader assemblyLoader)
4244
}
4345

4446
private void Watcher_Changed(object sender, FileSystemEventArgs e)
45-
{
47+
{
4648
// 判断是否是当前文件
4749
if (e.FullPath != _assemblyLoader.Setup.DllFullPath) return;
4850

49-
// 文件更改后,需要重新加载
50-
_assemblyLoader.Reload();
51+
// 事件是在另一个线程触发的,直接重载会报错
52+
// 切换到主线程执行
53+
Application.Current.Dispatcher.Invoke(() =>
54+
{
55+
// 文件更改后,需要重新加载
56+
_assemblyLoader.Reload();
57+
});
5158
}
5259
}
5360
}

MSAddinTest/Core/Loader/PluginAssemblyLoader.cs

+46-17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using MSAddinTest.Utils;
55
using System;
66
using System.Collections.Generic;
7+
using System.Globalization;
78
using System.IO;
89
using System.Linq;
910
using System.Reflection;
@@ -46,23 +47,34 @@ public PluginAssemblyLoader(LoaderSetup pluginDomainSetup)
4647
private List<ExecutorBase> _executors = new List<ExecutorBase>();
4748

4849
private string _lastFileHash = "";
50+
private Assembly _currentAssembly;
4951
public FuncResult LoadAssembly()
5052
{
5153
try
5254
{
55+
// 判断文件是否存在
56+
if (!File.Exists(Setup.DllFullPath))
57+
{
58+
return new FuncResult(false, "文件不存在");
59+
}
60+
5361
// 验证文件 hash 值
54-
var newFileHash = FileHelper.GetFileHash(Setup.DllFullPath);
55-
if (_lastFileHash == newFileHash)
56-
return new FuncResult(false, "文件未改变");
57-
else
58-
_lastFileHash = newFileHash;
62+
//var newFileHash = FileHelper.GetFileHash(Setup.DllFullPath);
63+
//if (_lastFileHash == newFileHash)
64+
// return new FuncResult(false, "文件未改变");
65+
//else
66+
// _lastFileHash = newFileHash;
67+
68+
// 执行卸载逻辑
69+
_msAddins.ForEach(x => x.Unloaded());
70+
_msAddins.Clear();
5971

6072
// 读取文件然后加载
6173
byte[] bytes = File.ReadAllBytes(Setup.DllFullPath);
62-
var assembly = Assembly.Load(bytes);
74+
_currentAssembly = Assembly.Load(bytes);
6375

64-
var results = BuilderExecutors(assembly);
65-
_executors = results.ToList();
76+
_executors.Clear();
77+
BuilderExecutors(_currentAssembly);
6678

6779
return new FuncResult(true);
6880
}
@@ -72,8 +84,6 @@ public FuncResult LoadAssembly()
7284
}
7385
}
7486

75-
76-
7787
/// <summary>
7888
/// 生成执行器
7989
/// </summary>
@@ -82,18 +92,31 @@ protected virtual IEnumerable<ExecutorBase> BuilderExecutors(Assembly assembly)
8292
{
8393
var results = new List<ExecutorBase>();
8494

85-
// 获取类执行器
86-
results.AddRange(GenerateClassExecutor(assembly));
95+
AddExecutors(GenerateClassExecutor(assembly));
8796

8897
// 静态方法执行器
89-
results.AddRange(GenerateStaticMethodExecutor(assembly));
98+
AddExecutors(GenerateStaticMethodExecutor(assembly));
9099

91100
// 添加 addin 执行器
92-
results.AddRange(GenerateAddinExecutor(assembly));
101+
AddExecutors(GenerateAddinExecutor(assembly));
93102

94103
return results;
95104
}
96105

106+
private void AddExecutors(IEnumerable<ExecutorBase> executors)
107+
{
108+
foreach (var executor in executors)
109+
{
110+
var executorTemp = _executors.Find(x => x.IsSame(executor));
111+
// 如果没找到或者优先级比原来高,则添加
112+
if (executorTemp == null || executorTemp.Priority < executor.Priority)
113+
{
114+
_executors.Remove(executorTemp);
115+
_executors.Add(executor);
116+
}
117+
}
118+
}
119+
97120
// 获取类执行器
98121
private IEnumerable<ExecutorBase> GenerateClassExecutor(Assembly assembly)
99122
{
@@ -137,9 +160,9 @@ private IEnumerable<ExecutorBase> GenerateStaticMethodExecutor(Assembly assembly
137160
{
138161
// 获取参数
139162
var paraInfos = methodInfo.GetParameters();
140-
if (paraInfos.Length != 1 || !typeof(IMSTestArg).IsAssignableFrom(paraInfos[0].ParameterType))
163+
if (paraInfos.Length != 1 || !typeof(string).IsAssignableFrom(paraInfos[0].ParameterType))
141164
{
142-
MessageCenter.Instance.ShowDebugMessage($"静态方法 {methodInfo.Name} 的参数个数必须有且只有一个 IMSTestArg 参数", "", false);
165+
MessageCenter.Instance.ShowDebugMessage($"静态方法 {methodInfo.Name} 的参数个数必须有且只有一个 string 参数", "", false);
143166
continue;
144167
};
145168

@@ -153,6 +176,7 @@ private IEnumerable<ExecutorBase> GenerateStaticMethodExecutor(Assembly assembly
153176
return results;
154177
}
155178

179+
private List<MSTest_Addin> _msAddins = new List<MSTest_Addin>();
156180
// 读取addin执行器
157181
private IEnumerable<ExecutorBase> GenerateAddinExecutor(Assembly assembly)
158182
{
@@ -166,9 +190,14 @@ private IEnumerable<ExecutorBase> GenerateAddinExecutor(Assembly assembly)
166190
// 找到后立即进行初始化
167191
try
168192
{
169-
var addin = Activator.CreateInstance(pluginType, IntPtr.Zero) as MSTest_Addin;
193+
var addin = Activator.CreateInstance(pluginType,
194+
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
195+
null,
196+
new object[] { IntPtr.Zero }, CultureInfo.CurrentCulture) as MSTest_Addin;
197+
170198
// 进行初始化
171199
addin.Init(Index.MSAddin.Instance);
200+
_msAddins.Add(addin);
172201
}
173202
catch (Exception ex)
174203
{

MSAddinTest/Core/Loader/PluginAssemblyLoader_Methods.cs

+9-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using MSAddinTest.MSTestInterface;
22
using System;
33
using System.Collections.Generic;
4+
using System.Globalization;
45
using System.Linq;
6+
using System.Reflection;
57
using System.Text;
68
using System.Threading.Tasks;
79

@@ -12,27 +14,22 @@ public partial class PluginAssemblyLoader
1214
/// <summary>
1315
/// 实例化执行对象并执行
1416
/// </summary>
15-
/// <param name="name"></param>
16-
/// <param name="arg"></param>
17+
/// <param name="nameWithParams"></param>
1718
/// <returns></returns>
18-
public FuncResult Execute(string name, IMSTestArg arg)
19+
public FuncResult Execute(string nameWithParams)
1920
{
20-
var nameTemp = name.Trim().ToLower();
21+
var nameTemp = nameWithParams.Trim().ToLower();
2122
// 对名称进行匹配
2223
// 如果是 keyin,通过匹配前缀是否为 keyin 来确定
2324
// 名称不区分大小写
24-
var executors = _executors.FindAll(x => x.IsMatch(name, out _, out _));
25+
var executors = _executors.FindAll(x => x.IsMatch(nameWithParams, out _, out _));
2526

2627
foreach (var executor in executors)
2728
{
2829
// 获取参数
29-
executor.IsMatch(name, out var executorName, out var strArg);
30-
if (!string.IsNullOrEmpty(strArg))
31-
{
32-
arg.UnparsedParams = strArg.Trim();
33-
}
30+
executor.IsMatch(nameWithParams, out var executorName, out var strArg);
3431

35-
executor.Execute(arg);
32+
executor.Execute(strArg.Trim());
3633
}
3734

3835
return new FuncResult(true)
@@ -41,13 +38,12 @@ public FuncResult Execute(string name, IMSTestArg arg)
4138
};
4239
}
4340

41+
4442
/// <summary>
4543
/// 重新加载
4644
/// </summary>
4745
public void Reload()
4846
{
49-
// 先对原来的 keyin 执行卸载程序
50-
5147
LoadAssembly();
5248
}
5349
}

0 commit comments

Comments
 (0)