Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: uyoufu/MSAddinTest
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.1
Choose a base ref
...
head repository: uyoufu/MSAddinTest
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Mar 9, 2023

  1. perf: 优化说明文档

    uyoufu committed Mar 9, 2023
    Copy the full SHA
    47c2ca3 View commit details
  2. perf: 优化说明文档

    uyoufu committed Mar 9, 2023
    Copy the full SHA
    80103a0 View commit details

Commits on Mar 16, 2023

  1. Copy the full SHA
    50bfe98 View commit details
  2. perf: 优化插件提示

    uyoufu committed Mar 16, 2023
    Copy the full SHA
    a5e7fe4 View commit details

Commits on Mar 17, 2023

  1. perf: 优化addin卸载接口

    uyoufu committed Mar 17, 2023
    Copy the full SHA
    cd0e7be View commit details
  2. perf: 优化重载逻辑

    uyoufu committed Mar 17, 2023
    Copy the full SHA
    df6de63 View commit details

Commits on Mar 26, 2023

  1. Copy the full SHA
    fce4e0a View commit details

Commits on May 16, 2023

  1. perf: 修改readme\

    uyoufu committed May 16, 2023
    Copy the full SHA
    cbbae75 View commit details
  2. perf: 修改 readme

    uyoufu committed May 16, 2023
    Copy the full SHA
    04d4cca View commit details
  3. perf: 修改内容

    uyoufu committed May 16, 2023
    Copy the full SHA
    6628c8c View commit details
  4. perf: 修改内容

    uyoufu committed May 16, 2023
    Copy the full SHA
    8867e38 View commit details
  5. perf: 更新

    uyoufu committed May 16, 2023
    Copy the full SHA
    16e1d84 View commit details

Commits on May 17, 2023

  1. Copy the full SHA
    1c011c2 View commit details
  2. perf: 更改版本号

    uyoufu committed May 17, 2023
    Copy the full SHA
    4797b6f View commit details

Commits on Nov 15, 2023

  1. Copy the full SHA
    390b0f2 View commit details
  2. Copy the full SHA
    ad3a5bf View commit details
  3. Copy the full SHA
    46bae2b View commit details

Commits on Nov 17, 2023

  1. Copy the full SHA
    31cbc66 View commit details

Commits on Nov 24, 2023

  1. Copy the full SHA
    1201259 View commit details

Commits on Dec 8, 2023

  1. Copy the full SHA
    0f2c384 View commit details
  2. Copy the full SHA
    0898b0b View commit details
  3. fix: 修复编码错误

    uyoufu committed Dec 8, 2023
    Copy the full SHA
    299f5eb View commit details

Commits on Feb 21, 2024

  1. perf: 修改readme

    uyoufu committed Feb 21, 2024
    Copy the full SHA
    b37f282 View commit details

Commits on Feb 23, 2024

  1. Copy the full SHA
    5d10db7 View commit details

Commits on Feb 24, 2024

  1. release: 发布 v1.0.6版本

    uyoufu committed Feb 24, 2024
    Copy the full SHA
    6c11e9c View commit details

Commits on Mar 5, 2024

  1. Copy the full SHA
    be041ae View commit details

Commits on May 23, 2024

  1. perf: 升级到4.8

    uyoufu committed May 23, 2024
    Copy the full SHA
    ffb6fea View commit details

Commits on Aug 22, 2024

  1. refactor: 规范接口命名

    uyoufu committed Aug 22, 2024
    Copy the full SHA
    d8b836d View commit details
  2. feat: 更新 readme

    uyoufu committed Aug 22, 2024
    Copy the full SHA
    4d12545 View commit details
Showing with 425 additions and 343 deletions.
  1. +1 −0 MSAddinTest/.gitignore
  2. +3 −3 MSAddinTest/App.config
  3. +2 −1 MSAddinTest/Core/Command/InstallCommand.cs
  4. +5 −5 MSAddinTest/Core/Command/LoadPluginCommand.cs
  5. +3 −1 MSAddinTest/Core/Command/LoadPluginsWhenStartupCommand.cs
  6. +3 −2 MSAddinTest/Core/Command/ReloadPluginCommand.cs
  7. +3 −11 MSAddinTest/Core/Command/RunPluginCommand.cs
  8. +1 −1 MSAddinTest/Core/Command/UninstallCommand.cs
  9. +4 −2 MSAddinTest/Core/Command/UnloadPluginCommand.cs
  10. +3 −1 MSAddinTest/Core/Command/UpdateSettingsCommand.cs
  11. +2 −14 MSAddinTest/Core/Executor/AddinExecutor.cs
  12. +4 −7 MSAddinTest/Core/Executor/ClassExecutor.cs
  13. +2 −6 MSAddinTest/Core/Executor/ExecutorBase.cs
  14. +4 −14 MSAddinTest/Core/Executor/StaticMethodExecutor.cs
  15. +6 −0 MSAddinTest/Core/FuncResult.cs
  16. +29 −9 MSAddinTest/Core/Loader/AutoReloader.cs
  17. +15 −19 MSAddinTest/Core/Loader/PluginAssemblyLoader.cs
  18. +7 −6 MSAddinTest/Core/Loader/PluginAssemblyLoader_Events.cs
  19. +14 −15 MSAddinTest/Core/Loader/PluginAssemblyLoader_Methods.cs
  20. +27 −0 MSAddinTest/Core/Message/MessageManager.cs
  21. +2 −2 MSAddinTest/Core/Settings/PluginSetting.cs
  22. +1 −1 MSAddinTest/{MSTestInterface → Interfaces}/IMSTest.cs
  23. +2 −2 MSAddinTest/{MSTestInterface/IMSTest_Class.cs → Interfaces/ITestClass.cs}
  24. +2 −2 MSAddinTest/{MSTestInterface/IMSTest_StaticMethod.cs → Interfaces/ITestStaticMethod.cs}
  25. +7 −3 MSAddinTest/{MSTestInterface → Interfaces}/MSTestAttribute.cs
  26. +47 −0 MSAddinTest/Interfaces/TestAddin.cs
  27. +15 −10 MSAddinTest/MSAddinTest.csproj
  28. +17 −0 MSAddinTest/MSAddinTest.nuspec
  29. +0 −40 MSAddinTest/MSTestInterface/MSTest_Addin.cs
  30. +2 −2 MSAddinTest/Properties/AssemblyInfo.cs
  31. +24 −32 MSAddinTest/Properties/Resources.Designer.cs
  32. +13 −17 MSAddinTest/Properties/Settings.Designer.cs
  33. 0 MSAddinTest/{Index → Startup}/Commands.xml
  34. +2 −11 MSAddinTest/{Index → Startup}/KeyinFuncs.cs
  35. +1 −1 MSAddinTest/{Index → Startup}/MSAddin.cs
  36. +4 −0 MSUtils/TestClass.cs
  37. +130 −88 Readme.md
  38. +1 −1 TestAddinPlugin/TestAddin/PluginAddin.cs
  39. +1 −1 TestAddinPlugin/TestAddin/PluginKeyinFuncs.cs
  40. +9 −10 TestAddinPlugin/TestAddinPlugin.csproj
  41. +6 −2 TestAddinPlugin/TestClassExecutor.cs
  42. +1 −1 TestAddinPlugin/TestStaticMethodExecutor.cs
1 change: 1 addition & 0 deletions MSAddinTest/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.nupkg
6 changes: 3 additions & 3 deletions MSAddinTest/App.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
</configuration>
3 changes: 2 additions & 1 deletion MSAddinTest/Core/Command/InstallCommand.cs
Original file line number Diff line number Diff line change
@@ -21,7 +21,8 @@ public override FuncResult Start()

// 读取值并修改
string configContent = File.ReadAllText(personalConfPath);
string autoloadSentence = "\r\n%level Organization\r\nMS_DGNAPPS > MSAddinTest";
//string autoloadSentence = "\r\n%level Organization\r\nMS_DGNAPPS > MSAddinTest";
string autoloadSentence = "\r\nMS_DGNAPPS > MSAddinTest";
if (!configContent.Contains(autoloadSentence))
{
// 添加语句使其自动加载
10 changes: 5 additions & 5 deletions MSAddinTest/Core/Command/LoadPluginCommand.cs
Original file line number Diff line number Diff line change
@@ -38,12 +38,12 @@ public override FuncResult Start()
{
string pluginName = Path.GetFileNameWithoutExtension(dllPath);

if (PluginContainer.ContainsKey(pluginName))
if (PluginContainer.TryGetValue(pluginName,out var existLoader))
{
return new FuncResult(false)
{
StatusCode = StatusCode.AlreadyLoaded
};
// 重载插件
existLoader.Reload();
MessageCenter.Instance.ShowInfoMessage($"找到相同插件 {existLoader.Setup.PluginName},重载成功!", "", false);
continue;
}

var setup = new LoaderSetup()
4 changes: 3 additions & 1 deletion MSAddinTest/Core/Command/LoadPluginsWhenStartupCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MSAddinTest.Core.Loader;
using Bentley.MstnPlatformNET;
using MSAddinTest.Core.Loader;
using System;
using System.Collections.Generic;
using System.IO;
@@ -27,6 +28,7 @@ public override FuncResult Start()
}

PluginContainer.Add(loader);
MessageCenter.Instance.ShowInfoMessage($"{loader.Setup.PluginName} 已自动加载!", "", false);
}

return new FuncResult(true);
5 changes: 3 additions & 2 deletions MSAddinTest/Core/Command/ReloadPluginCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -22,7 +23,7 @@ public override FuncResult Start()
if (PluginContainer.TryGetValue(_pluginName, out var container))
{
container.Reload();
System.Windows.MessageBox.Show("重载成功!");
MessageCenter.Instance.ShowInfoMessage($"{_pluginName} 重载成功!", "", false);
}

return new FuncResult(true);
14 changes: 3 additions & 11 deletions MSAddinTest/Core/Command/RunPluginCommand.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
using Bentley.MstnPlatformNET;
using MSAddinTest.MSTestInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System;
using System.Windows;

namespace MSAddinTest.Core.Command
@@ -48,12 +40,12 @@ public override FuncResult Start()
}
catch (Exception ex)
{
MessageCenter.Instance.ShowErrorMessage(ex.Message, ex.StackTrace, true);
Message.MessageManager.ShowException(ex);
}

if (executorsCount == 0)
{
MessageBox.Show($"未找到名为{_executorName}的执行器");
MessageBox.Show($"未找到名为{_executorName} 的执行器");
}

return new FuncResult(executorsCount > 0);
2 changes: 1 addition & 1 deletion MSAddinTest/Core/Command/UninstallCommand.cs
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ public override FuncResult Start()

// 读取值并修改
string configContent = File.ReadAllText(personalConfPath);
string autoloadSentence = "\r\n%level Organization\r\nMS_DGNAPPS > MSAddinTest";
string autoloadSentence = "\r\nMS_DGNAPPS > MSAddinTest";
if (configContent.Contains(autoloadSentence))
{
configContent = configContent.Replace(autoloadSentence, "");
6 changes: 4 additions & 2 deletions MSAddinTest/Core/Command/UnloadPluginCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MSAddinTest.Core.Settings;
using Bentley.MstnPlatformNET;
using MSAddinTest.Core.Settings;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -19,7 +20,7 @@ public UnloadPluginCommand(string pluginName)
/// <summary>
/// 待卸载的插件名称
/// </summary>
private string _pluginNameToUnload { get; set; }
private readonly string _pluginNameToUnload;

public override FuncResult Start()
{
@@ -29,6 +30,7 @@ public override FuncResult Start()
// 从存储中去掉记录
PluginSetting.RemovePluginSetting(_pluginNameToUnload);

MessageCenter.Instance.ShowInfoMessage($"{_pluginNameToUnload} 已卸载!", "", false);
return new FuncResult(true);
}
}
4 changes: 3 additions & 1 deletion MSAddinTest/Core/Command/UpdateSettingsCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MSAddinTest.Core.Settings;
using Bentley.MstnPlatformNET;
using MSAddinTest.Core.Settings;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -79,6 +80,7 @@ public override FuncResult Start()
// 保存设置
PluginSetting.Save();

MessageCenter.Instance.ShowInfoMessage("设置已保存!", "", false);
return new FuncResult(true);
}
}
16 changes: 2 additions & 14 deletions MSAddinTest/Core/Executor/AddinExecutor.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using MSAddinTest.MSTestInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace MSAddinTest.Core.Executor
{
@@ -22,14 +17,7 @@ public override void Execute(string arg)
if (MethodInfo == null) return;

// 调用静态方法
try
{
MethodInfo.Invoke(null, new object[] { arg });
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
MethodInfo.Invoke(null, new object[] { arg });
}
}
}
11 changes: 4 additions & 7 deletions MSAddinTest/Core/Executor/ClassExecutor.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using MSAddinTest.MSTestInterface;
using MSAddinTest.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace MSAddinTest.Core.Executor
{
@@ -31,8 +28,8 @@ public ClassExecutor(Type type) : base(type)

public override void Execute(string arg)
{
var instance = Activator.CreateInstance(Type, BindingFlags.Public | BindingFlags.NonPublic);
if (instance is IMSTest_Class plugin)
var instance = Activator.CreateInstance(Type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.NonPublic, null, new object[] { }, null);
if (instance is ITestClass plugin)
{
plugin.Execute(arg);
}
@@ -46,7 +43,7 @@ public override void Execute(string arg)
/// <returns></returns>
public override bool IsSame(ExecutorBase executor)
{
if (!(executor is ClassExecutor))return false;
if (!(executor is ClassExecutor)) return false;

return base.IsSame(executor);
}
8 changes: 2 additions & 6 deletions MSAddinTest/Core/Executor/ExecutorBase.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
using MSAddinTest.MSTestInterface;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace MSAddinTest.Core.Executor
{
@@ -46,7 +42,7 @@ public ExecutorBase(Type type)
/// <summary>
/// 通过输入字符串匹配当前执行器
/// </summary>
/// <param name="inputStr"></param>
/// <param name="inputStr">用户输入的字符串</param>
/// <param name="name"></param>
/// <param name="args"></param>
/// <returns></returns>
18 changes: 4 additions & 14 deletions MSAddinTest/Core/Executor/StaticMethodExecutor.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using MSAddinTest.MSTestInterface;
using MSAddinTest.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace MSAddinTest.Core.Executor
{
@@ -25,7 +22,8 @@ public StaticMethodExecutor(MethodInfo methodInfo) : base(null)
public StaticMethodExecutor(Type type, string methodName) : base(type)
{
// 获取 MethodInfo
var methodInfo = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var methodInfo = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) ?? throw new NullReferenceException($"无法在 {type} 中找到静态方法 {methodName}");

SetMthodInfo(methodInfo);
}

@@ -55,15 +53,7 @@ public override void Execute(string arg)
if (MethodInfo == null) return;

// 调用静态方法
try
{
MethodInfo.Invoke(null, new object[] { arg });

}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
MethodInfo.Invoke(null, new object[] { arg });
}
}
}
6 changes: 6 additions & 0 deletions MSAddinTest/Core/FuncResult.cs
Original file line number Diff line number Diff line change
@@ -50,5 +50,11 @@ public FuncResult(bool ok,string message):this(ok)
/// 数据
/// </summary>
public object Data { get; set; }

// 与 bool 类型的隐式转换
public static implicit operator bool(FuncResult result)
{
return result.Ok;
}
}
}
38 changes: 29 additions & 9 deletions MSAddinTest/Core/Loader/AutoReloader.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;

namespace MSAddinTest.Core.Loader
@@ -14,8 +16,13 @@ namespace MSAddinTest.Core.Loader
/// </summary>
internal class AutoReloader
{
private FileSystemWatcher _watcher;
private PluginAssemblyLoader _assemblyLoader;
private readonly FileSystemWatcher _watcher;
private readonly PluginAssemblyLoader _assemblyLoader;
private readonly Timer _reloadTimer = new Timer(1000)
{
Enabled = false,
AutoReset = true
};

public AutoReloader(PluginAssemblyLoader assemblyLoader)
{
@@ -27,6 +34,7 @@ public AutoReloader(PluginAssemblyLoader assemblyLoader)
NotifyFilter = NotifyFilters.LastWrite
};
_watcher.Changed += Watcher_Changed;
_reloadTimer.Elapsed += ReloadTimer_Elapsed;

// 从设置中获取是否自动重载
var setting = _assemblyLoader.Setup.PluginSetting;
@@ -35,26 +43,38 @@ public AutoReloader(PluginAssemblyLoader assemblyLoader)
// 监听数据变化
setting.SettingChanged += (arg) =>
{
if(arg.FieldName == "autoReload" && bool.TryParse(arg.Value,out bool result))
if (arg.FieldName == "autoReload" && bool.TryParse(arg.Value, out bool result))
{
_watcher.EnableRaisingEvents = result;
}
};
}

}

private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
// 判断是否是当前文件
if (e.FullPath != _assemblyLoader.Setup.DllFullPath) return;
{
// 只有当前文件才触发
if (e.FullPath != _assemblyLoader.Setup.DllFullPath)
{
return;
}

// 多次触发时,重置计时器
_reloadTimer.Stop();
_reloadTimer.Start();
}

private void ReloadTimer_Elapsed(object sender, ElapsedEventArgs e)
{
_reloadTimer.Stop();
// 事件是在另一个线程触发的,直接重载会报错
// 切换到主线程执行
Application.Current.Dispatcher.Invoke(() =>
{
// 文件更改后,需要重新加载
_assemblyLoader.Reload();
});

});
}
}
}
34 changes: 15 additions & 19 deletions MSAddinTest/Core/Loader/PluginAssemblyLoader.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Bentley.MstnPlatformNET;
using MSAddinTest.Core.Executor;
using MSAddinTest.MSTestInterface;
using MSAddinTest.Utils;
using MSAddinTest.Interfaces;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -41,12 +40,11 @@ public PluginAssemblyLoader(LoaderSetup pluginDomainSetup)
private readonly AutoReloader _autoReloader;

// 所有根目录下的 dll 文件
private List<string> _allFileNames;
private readonly List<string> _allFileNames;

// 从程序集中读取的执行器
private List<ExecutorBase> _executors = new List<ExecutorBase>();
private readonly List<ExecutorBase> _executors = new List<ExecutorBase>();

private string _lastFileHash = "";
private Assembly _currentAssembly;
public FuncResult LoadAssembly()
{
@@ -66,7 +64,7 @@ public FuncResult LoadAssembly()
// _lastFileHash = newFileHash;

// 执行卸载逻辑
_msAddins.ForEach(x => x.Unloaded());
_msAddins.ForEach(x => x.NotifyOnUnloaded(new AddIn.UnloadedEventArgs(AddIn.UnloadReasons.ExitByOtherApp)));
_msAddins.Clear();

// 读取文件然后加载
@@ -124,16 +122,14 @@ private IEnumerable<ExecutorBase> GenerateClassExecutor(Assembly assembly)
List<ExecutorBase> results = new List<ExecutorBase>();

// 生成运行数据
var iPluginType = typeof(IMSTest_Class);
var iPluginType = typeof(ITestClass);
var pluginTypes = assembly.GetTypes().Where(x => !x.IsInterface && !x.IsAbstract && iPluginType.IsAssignableFrom(x));
// 获取非 addin 插件
var commonPluginTypes = pluginTypes;
foreach (var pluginType in commonPluginTypes)
{
var commonPluginTypes = pluginTypes;
foreach (var pluginType in commonPluginTypes)
{
var classExecutor = new ClassExecutor(pluginType);
results.Add(classExecutor);
}
var classExecutor = new ClassExecutor(pluginType);
results.Add(classExecutor);
}

return results;
@@ -149,7 +145,7 @@ private IEnumerable<ExecutorBase> GenerateStaticMethodExecutor(Assembly assembly
List<ExecutorBase> results = new List<ExecutorBase>();

// 生成运行数据
var iPluginType = typeof(IMSTest_StaticMethod);
var iPluginType = typeof(ITestStaticMethod);
var pluginTypes = assembly.GetTypes().Where(x => !x.IsInterface && !x.IsAbstract && iPluginType.IsAssignableFrom(x));
// 获取静态方法执行器
{
@@ -163,7 +159,7 @@ private IEnumerable<ExecutorBase> GenerateStaticMethodExecutor(Assembly assembly
var paraInfos = methodInfo.GetParameters();
if (paraInfos.Length != 1 || !typeof(string).IsAssignableFrom(paraInfos[0].ParameterType))
{
MessageCenter.Instance.ShowDebugMessage($"静态方法 {methodInfo.Name} 的参数个数必须有且只有一个 string 参数", "", false);
MessageCenter.Instance.ShowErrorMessage($"静态方法 {methodInfo.Name} 的参数个数必须有且只有一个 string 参数", "", false);
continue;
};

@@ -177,12 +173,12 @@ private IEnumerable<ExecutorBase> GenerateStaticMethodExecutor(Assembly assembly
return results;
}

private List<MSTest_Addin> _msAddins = new List<MSTest_Addin>();
private readonly List<TestAddin> _msAddins = new List<TestAddin>();
// 读取addin执行器
private IEnumerable<ExecutorBase> GenerateAddinExecutor(Assembly assembly)
{
// 生成运行数据
var iPluginType = typeof(MSTest_Addin);
var iPluginType = typeof(TestAddin);
var allTypes = assembly.GetTypes();
var pluginTypes = allTypes.Where(x => x.IsSubclassOf(iPluginType));

@@ -194,7 +190,7 @@ private IEnumerable<ExecutorBase> GenerateAddinExecutor(Assembly assembly)
var addin = Activator.CreateInstance(pluginType,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { IntPtr.Zero }, CultureInfo.CurrentCulture) as MSTest_Addin;
new object[] { IntPtr.Zero }, CultureInfo.CurrentCulture) as TestAddin;
// 完成后调用 run
// 在此处调用初始化内容
addin.Init(addin);
@@ -203,7 +199,7 @@ private IEnumerable<ExecutorBase> GenerateAddinExecutor(Assembly assembly)
}
catch (Exception ex)
{
System.Windows.MessageBox.Show("Addin初始化失败:" + ex.Message);
Message.MessageManager.ShowException(ex, "Addin 初始化失败:");
}
}

13 changes: 7 additions & 6 deletions MSAddinTest/Core/Loader/PluginAssemblyLoader_Events.cs
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ private void RegistryEvents()

private void AppDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
{
//MessageBox.Show(e.Exception.Message);
// Message.MessageManager.ShowException(e.Exception);
}

#region 加载需要的程序集
@@ -42,15 +42,16 @@ private Assembly AppDomain_TypeResolve(object sender, ResolveEventArgs args)

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
// 获取对应版本的程序集
// 获取最新版本的程序集
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
Assembly targetAssembly = assemblies.LastOrDefault(x => x.FullName.Contains(args.Name));
string assemblyName = args.Name.Split(',')[0].Trim();
Assembly targetAssembly = assemblies.LastOrDefault(x => x.FullName.Contains(assemblyName));

if (targetAssembly != null) return targetAssembly;

// 找到文件,然后加载
string targetFileName = args.Name.Split(',')[0];
string fileName = _allFileNames.Find(x => x.Contains(targetFileName));
// 找到文件,然后加载
string assemblyFileName = $"{assemblyName}.dll";
string fileName = _allFileNames.Find(x => x.EndsWith(assemblyFileName));
if (fileName == null) return null;

byte[] bytes = File.ReadAllBytes(fileName);
29 changes: 14 additions & 15 deletions MSAddinTest/Core/Loader/PluginAssemblyLoader_Methods.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
using MSAddinTest.MSTestInterface;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Bentley.MstnPlatformNET;

namespace MSAddinTest.Core.Loader
{
@@ -18,18 +11,19 @@ public partial class PluginAssemblyLoader
/// <returns></returns>
public FuncResult Execute(string nameWithParams)
{
var nameTemp = nameWithParams.Trim().ToLower();
// 使用正则表达式将多个空格转换成一个空格
nameWithParams = System.Text.RegularExpressions.Regex.Replace(nameWithParams, @"\s+", " ");
var nameTemp = nameWithParams.Trim();
// 对名称进行匹配
// 如果是 keyin,通过匹配前缀是否为 keyin 来确定
// 如果是 keyin ,通过匹配前缀是否为 keyin 来确定
// 名称不区分大小写
var executors = _executors.FindAll(x => x.IsMatch(nameWithParams, out _, out _));
var executors = _executors.FindAll(x => x.IsMatch(nameTemp, out _, out _));

foreach (var executor in executors)
{
// 获取参数
executor.IsMatch(nameWithParams, out var executorName, out var strArg);

executor.Execute(strArg.Trim());
executor.IsMatch(nameTemp, out var executorName, out var strArg);
executor.Execute(strArg);
}

return new FuncResult(true)
@@ -44,7 +38,12 @@ public FuncResult Execute(string nameWithParams)
/// </summary>
public void Reload()
{
LoadAssembly();
var reloadResult = LoadAssembly();
if (reloadResult)
{
// 提示成功
MessageCenter.Instance.ShowInfoMessage($"{Setup.PluginName} 插件重载成功!", "", false);
}
}
}
}
27 changes: 27 additions & 0 deletions MSAddinTest/Core/Message/MessageManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace MSAddinTest.Core.Message
{
internal class MessageManager
{
/// <summary>
/// 显示异常错误
/// </summary>
/// <param name="exception"></param>
/// <param name="titlePrefix"></param>
public static void ShowException(Exception exception, string titlePrefix = "")
{
if (exception.InnerException != null) exception = exception.InnerException;

var briefMessage = $"{titlePrefix}{exception.Message}";
MessageBox.Show(briefMessage);
MessageCenter.Instance.ShowErrorMessage(briefMessage, exception.StackTrace, false);
}
}
}
4 changes: 2 additions & 2 deletions MSAddinTest/Core/Settings/PluginSetting.cs
Original file line number Diff line number Diff line change
@@ -18,13 +18,13 @@ namespace MSAddinTest.Core.Settings
public class PluginSetting
{
private JObject _jsonConfig;
private string _savePath;
private readonly string _savePath;

public PluginSetting(object addin)
{
_savePath = Path.Combine(ConfigurationManager.GetVariable("_USTN_HOMEROOT"), $@"MSAddinTest\config.json");
// 监听Ord关闭事件,关闭之前要保存配置
Index.MSAddin.Instance.ExitDesignFileStateEvent += Instance_ExitDesignFileStateEvent;
Startup.MSAddin.Instance.ExitDesignFileStateEvent += Instance_ExitDesignFileStateEvent;

// 从指定目录读取配置文件
Read();
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
using System.Text;
using System.Threading.Tasks;

namespace MSAddinTest.MSTestInterface
namespace MSAddinTest.Interfaces
{
/// <summary>
/// 插件接口
Original file line number Diff line number Diff line change
@@ -4,12 +4,12 @@
using System.Text;
using System.Threading.Tasks;

namespace MSAddinTest.MSTestInterface
namespace MSAddinTest.Interfaces
{
/// <summary>
/// 类执行器的插件接口
/// </summary>
public interface IMSTest_Class:IMSTest
public interface ITestClass:IMSTest
{
/// <summary>
/// 执行插件方法
Original file line number Diff line number Diff line change
@@ -4,12 +4,12 @@
using System.Text;
using System.Threading.Tasks;

namespace MSAddinTest.MSTestInterface
namespace MSAddinTest.Interfaces
{
/// <summary>
/// 静态方法的入口
/// </summary>
public interface IMSTest_StaticMethod : IMSTest
public interface ITestStaticMethod : IMSTest
{
}
}
Original file line number Diff line number Diff line change
@@ -4,17 +4,21 @@
using System.Text;
using System.Threading.Tasks;

namespace MSAddinTest.MSTestInterface
namespace MSAddinTest.Interfaces
{
/// <summary>
/// Plugin特性
/// Plugin 特性
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class MSTestAttribute : Attribute
{
/// <summary>
/// 内部会将 name.Trim() 作为 Name
/// </summary>
/// <param name="name"></param>
public MSTestAttribute(string name)
{
Name = name;
Name = name.Trim();
}

/// <summary>
47 changes: 47 additions & 0 deletions MSAddinTest/Interfaces/TestAddin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Bentley.MstnPlatformNET.AddIn;

namespace MSAddinTest.Interfaces
{
/// <summary>
/// Addin 插件
/// </summary>
public abstract class TestAddin : IMSTest
{
protected TestAddin(IntPtr mdlDescriptor)
{
}

public virtual void Init(AddIn addIn)
{
Run(new string[] { });
}

protected abstract int Run(string[] commandLine);

/// <summary>
/// 卸载后手动清除向 Addin 中注册的一些事件
/// </summary>
protected virtual void OnUnloaded(UnloadedEventArgs eventArgs) { }

/// <summary>
/// 发送卸载完成通知
/// </summary>
/// <param name="eventArgs"></param>
public void NotifyOnUnloaded(UnloadedEventArgs eventArgs) => OnUnloaded(eventArgs);

/// <summary>
/// 隐式转换成 addin
/// </summary>
/// <param name="testAddin"></param>
public static implicit operator AddIn(TestAddin testAddin)
{
return Startup.MSAddin.Instance;
}
}
}
25 changes: 15 additions & 10 deletions MSAddinTest/MSAddinTest.csproj
Original file line number Diff line number Diff line change
@@ -8,12 +8,14 @@
<OutputType>Library</OutputType>
<RootNamespace>MSAddinTest</RootNamespace>
<AssemblyName>MSAddinTest</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<Microstation>D:\Program Files\Bentley\OpenRoads Designer 2023.00\OpenRoadsDesigner</Microstation>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
@@ -39,7 +41,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>C:\sw_Bentley\OpenRoads\sw_Standards\mdlapps\</OutputPath>
<OutputPath>$(Microstation)\Mdlapps\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@@ -59,6 +61,7 @@
<Reference Include="Bentley.DgnPlatformNET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4bf6c96a266e58d4, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(Microstation)\Bentley.DgnPlatformNET.dll</HintPath>
<EmbedInteropTypes>False</EmbedInteropTypes>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -105,22 +108,23 @@
<Compile Include="Core\Executor\StaticMethodExecutor.cs" />
<Compile Include="Core\Loader\PluginAssemblyLoader_Events.cs" />
<Compile Include="Core\Loader\PluginAssemblyLoader_Methods.cs" />
<Compile Include="Core\Message\MessageManager.cs" />
<Compile Include="Core\PluginDomainContainer.cs" />
<Compile Include="Core\PluginManager.cs" />
<Compile Include="Core\Settings\PluginSetting.cs" />
<Compile Include="Core\Settings\UpdateSettingArg.cs" />
<Compile Include="Core\StatusCode.cs" />
<Compile Include="Index\KeyinFuncs.cs" />
<Compile Include="Index\MSAddin.cs" />
<Compile Include="MSTestInterface\MSTest_Addin.cs" />
<Compile Include="Startup\KeyinFuncs.cs" />
<Compile Include="Startup\MSAddin.cs" />
<Compile Include="Interfaces\TestAddin.cs" />
<Compile Include="Utils\Ex_Json.cs" />
<Compile Include="Utils\FileHelper.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="MSTestInterface\IMSTest_Class.cs" />
<Compile Include="MSTestInterface\IMSTest.cs" />
<Compile Include="MSTestInterface\IMSTest_StaticMethod.cs" />
<Compile Include="MSTestInterface\MSTestAttribute.cs" />
<Compile Include="Interfaces\ITestClass.cs" />
<Compile Include="Interfaces\IMSTest.cs" />
<Compile Include="Interfaces\ITestStaticMethod.cs" />
<Compile Include="Interfaces\MSTestAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
@@ -140,6 +144,7 @@
<SubType>Designer</SubType>
</EmbeddedResource>
<None Include="Core\Settings\defaultSettings.json" />
<None Include="MSAddinTest.nuspec" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
@@ -149,7 +154,7 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Index\Commands.xml">
<EmbeddedResource Include="Startup\Commands.xml">
<SubType>Designer</SubType>
<LogicalName>CommandTable.xml</LogicalName>
</EmbeddedResource>
17 changes: 17 additions & 0 deletions MSAddinTest/MSAddinTest.nuspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>MSAddinTest</id>
<version>1.0.7</version>
<title>MSAddinTest</title>
<authors>galens</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">Apache-2.0</license>
<!-- <icon>icon.png</icon> -->
<projectUrl>https://github.com/GalensGan/MSAddinTest/</projectUrl>
<description>a framework for microstation addin or utils test, support hot reloading</description>
<releaseNotes></releaseNotes>
<copyright>copyright 2024</copyright>
<tags>Microstation AddinTest Test</tags>
</metadata>
</package>
40 changes: 0 additions & 40 deletions MSAddinTest/MSTestInterface/MSTest_Addin.cs

This file was deleted.

4 changes: 2 additions & 2 deletions MSAddinTest/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -51,5 +51,5 @@
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.4.1")]
[assembly: AssemblyFileVersion("0.4.1")]
[assembly: AssemblyVersion("1.1.0")]
[assembly: AssemblyFileVersion("1.1.0")]
56 changes: 24 additions & 32 deletions MSAddinTest/Properties/Resources.Designer.cs
30 changes: 13 additions & 17 deletions MSAddinTest/Properties/Settings.Designer.cs
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
using Bentley.DgnPlatformNET;
using Bentley.MstnPlatformNET;
using MSAddinTest.Core;
using MSAddinTest.Core;
using MSAddinTest.Core.Command;
using MSAddinTest.MSTestInterface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MSAddinTest.Index
namespace MSAddinTest.Startup
{
internal class KeyinFuncs
{
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
using System.Threading.Tasks;
using System.Windows;

namespace MSAddinTest.Index
namespace MSAddinTest.Startup
{
/// <summary>
/// Microstation Addin 入口
4 changes: 4 additions & 0 deletions MSUtils/TestClass.cs
Original file line number Diff line number Diff line change
@@ -8,6 +8,10 @@ namespace MSUtils
{
public class TestClass
{
/// <summary>
/// 测试异常
/// </summary>
/// <exception cref="NullReferenceException"></exception>
public static void NullException()
{
throw new NullReferenceException("test exception in reference");
218 changes: 130 additions & 88 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -2,81 +2,133 @@

## 简介

本插件名为:MSAddinTest,是一款面向 Microstation 的 Addin 管理测试插件。通过它,你可以在不关闭 Microstation 的情况下,重新修改编译加载 DLL 库
本插件名为:MSAddinTest,可以帮助开发者在不关闭 Microstation 的情况下,可以实现代码热重载与快速调试

你只需在 keyin 前加上 `MSTest test` 即可调用现有的 keyin 命令。
对代码的入侵小,使用时只需在 keyin 前加上 `MSTest test` 即可调用现有的 keyin 命令。

the name of this plugin is `MSAddinTest`,it's an efficient plugin for addin developing on Miscrostation platform witch allows you to hot-reload addin plugin。
The name of this plugin is `MSAddinTest`,it's an efficient plugin for addin developing on Miscrostation platform which allows you to hot-reload addin plugin。

it is so easy to use,when you want to invoke a keyin function,just put the string `MSTest test` before your addin keyin,aha,just it~

## 功能特点

1. 库热重载
1. 支持热重载

在进行 Microstation 调试过程中,仅可在方法内部进行修改,无法增加方法或者类等结构型操作,如果想要进行深度修改,只能关闭 Microstation,修改 Addin 库,编译,重新打开 Microstation,再开始调试。而启动 Microstation 相对费时,会浪费掉很多时间。

本插件主要解决这个痛点,提供了对库的热重载功能,可以在不关闭 Microstation 的情况下,重新修改编译加载 DLL 库。

2. 自动启动
2. 支持自动启动

支持一键配置在启动时加载。

3. 自动加载 DLL
3. 支持自动加载 DLL

支持配置启动时自动加载测试 DLL,可以指定自动加载某些库。

4. 支持断点调试

支持测试 DLL 的断点调试。

5. 搭建测试简单,代码入侵小,与正常开发异
5. 搭建测试简单,代码入侵小,与正常开发无异

测试 keyin 时,只需要 `MsTest test keyin` 即可执行测试,其它详见安装与使用。
测试 keyin 时,只需要 `MSTest test keyin` 即可执行测试,其它详见安装与使用。

## 安装与使用
## 为什么不使用VS的原生热重载?

### 插件安装
vs 热重载对于以下修改不支持:

- 添加方法、字段、构造函数等
- 动态对象的增改
- [More ...](https://learn.microsoft.com/zh-cn/visualstudio/debugger/supported-code-changes-csharp?view=vs-2022#unsupported-changes-to-code)

而 MSAddinTest 没有上述限制。

## MSAddinTest 安装

1. 拷贝 `MSAddinTest.dll` 到 Microstaion 中的 `mdlapp` 目录里
2. 启动 Microstation
3. 加载 `MSAddinTest.dll`
4. 输入 `MSTest install` 开启自动启动。可以输入 `MSTest uninstall` 关闭自动启动。

### 测试标记
> 支持基于 Microstation 的所有 Bentley 产品
## MSAddinTest 使用

### Debug 流程

**调试:**

1. [标记调用入口](#标记调用入口)
2. 编译代码
3. 启动 Microstation

1. 输入 keyin `MSTest load` 加载待测试 dll
2. VS 中附加进程到 Micostation 开启调试(快捷键:Ctrl+Alt+P)
3. 输入 `MSTest test keyin` 调用待测试的 keyin 命令

**重新修改:**

1. 关闭调试

2. 编辑代码

3. 重新编译

4. 在 Microstation 中使用 `MsTest reload DllName` 来重新加载库文件

MSAddinTest 支持对以下三种方式的接口进行调用。
这一步可以通过设置实现自动重载([转到 MSTest set](#mstest-set))来跳过。

5. 在 vs 中将 Microstation 重新附加到进程(快捷键:Shift+Alt+P)

6. 输入 `MSTest test keyin` 进行调试

### 标记调用入口

对于 Addin、静态方法、实例方法,标记调用入口的方式略有不同,下面分别进行介绍。

#### Addin 库

想要支持 Addin 库的调用,须将自定义的 `Addin` 类继承抽象类 `MSTest_Addin`
想要支持 Addin 库的调用,须将自定义的 `Addin` 类继承抽象类 `TestAddin`

示例如下:

``` csharp
/// <summary>
/// 测试 addin 调试
/// 1. 继承抽象类 MSTest_Addin
/// 1. 继承抽象类 TestAddin
/// 2. 在 Init 中获取传递的 addin 供当前库使用
/// </summary>
[AddIn(MdlTaskID = "TestAddinPlugin")]
internal class PluginAddin : MSTest_Addin
internal class PluginAddin
// 通过 #if DEBUG 针对不同的编译场景编写不同的代码
#if DEBUG
// debug 时,继承 TestAddin,实现热重载
: TestAddin
{
// 可以在此处重写初始化方法,一般不进行重写
// 该方法为 TestAddin 特有
public override void Init(AddIn addin)
{
// 重写时,一定要调用父类中的方法
base.Init(addin);
}
#else
// 非 debug 模型式,直接继承 AddIn
: AddIn
{
#endif

public static AddIn Instance { get; private set; }
public PluginAddin(IntPtr mdlDescriptor) : base(mdlDescriptor)
{
// 在此处可以保存 this 用于窗体的加载
// this 是 MSTest_Addin 实例,可以转换成 Addin 是因为 MSTest_Addin 进行了隐式转换
// 在此处可以保存 this 用于窗体的加载
// this 是 TestAddin 实例,可以转换成 Addin 是因为 TestAddin 进行了隐式转换
Instance = this;
}

// 可以在此处重写初始化方法,一般不进行重写
public override void Init(AddIn addin)
{
}

// 在这个方法中释放资源
public override void Unloaded()
public override void Unloaded(UnloadedEventArgs eventArgs)
{
// 当插件重载时,可以在此处卸载上一次加载的事件
}
@@ -95,13 +147,14 @@ internal class PluginAddin : MSTest_Addin

**其它:**

通过上述配置后,插件会自动读取命令表,从而根据命令表查找到 Keyin 对应的静态方法。一般 keyin 会有多个单词,如果觉得通过 MSTest test + keyin 的方式太长,可以在静态方法中添加 `MSTestAttribute` 特性来添加 keyin 别名。
通过上述配置后,插件会自动读取命令表,从而根据命令表查找到 Keyin 对应的静态方法。

一般 keyin 会有多个单词,如果觉得通过 MSTest test + keyin 的方式太长,可以在静态方法中添加 `MSTestAttribute` 特性来添加 keyin 别名。

如下所示:

``` csharp
// 可以通过 MSTest test element 来调用
// 对于下列 keyin 对应的静态方法, 不仅可以通过 MSTest test keyin 来调用,还可以通过 MSTest test element 来调用
[MSTest("element",Description ="这是keyin别名")]
public static void TestElement(string unparsed)
{
@@ -113,20 +166,20 @@ public static void TestElement(string unparsed)

除了 keyin 对应的静态方法外,想要调用其它静态方法,须满足以下条件:

1. 类继承接口 IMSTest_StaticMethod
2. 静态方法添加特性 MSTestAttribute
1. 类继承接口 `ITestStaticMethod`
2. 静态方法添加特性 `MSTestAttribute`
3. 静态方法有且仅有一个 string 参数

示例如下:

``` csharp
/// <summary>
/// 测试静态方法
/// 1. 类继承接口 IMSTest_StaticMethod
/// 1. 类继承接口 ITestStaticMethod
/// 2. 静态方法添加特性 MSTest
/// 3. 静态方法有且仅有一个IMSTestArg参数
/// </summary>
public class TestStaticMethodExecutor : IMSTest_StaticMethod
public class TestStaticMethodExecutor : ITestStaticMethod
{
[MSTest("static")]
public static object Execute(string arg)
@@ -149,21 +202,22 @@ public class TestStaticMethodExecutor : IMSTest_StaticMethod

本插件也支持对实例的调试,须满足以下条件:

1. 继承接口 IMSTest_Class
2. 类上添加特性 MSTestAttribute
1. 继承接口 `ITestClass`
2. 类上添加特性 `MSTestAttribute`

示例如下:

``` csharp
/// <summary>
/// 测试类执行器
/// 1. 继承接口 IMSTest_Class
/// 1. 继承接口 ITestClass
/// 2. 类添加特性 MSTest
/// </summary>
[MSTest("class", Description = "测试 IClassPlugin 插件")]
internal class TestClassExecutor : IMSTest_Class
internal class TestClassExecutor : ITestClass
{
// 实现接口
// 实现接口 ITestClass
// 该接口为实例初始化后的调用入口
public void Execute(string arg)
{
MessageBox.Show("IClassPlugin 被调用了!");
@@ -177,58 +231,31 @@ internal class TestClassExecutor : IMSTest_Class

通过 `MSTest test name` 调用。

#### 混合使用
#### 混合标记

可以将上述三种方式混合使用,可以在一个类上同时实现 `Addin``静态方法 ``实例方法` 三种测试方式。

其中 Addin 和 静态方法 的调用名称一样时,保留 Addin 测试入口。

## 引用 DLL 更新

假设有一个 addin.dll,它引用了一个开发中的功能库 utils.dll,当我们修改 utils.dll 时,也希望插件可以热加载,及时反馈到调试上。

要使引用的 Dll 变动触发热重载,需要给引用的程序集添加 AssemblyVersion 自增版本号(当然,也可以每次修改后手动修改该版本号)。

自增版本号修改方法如下:

1.`Properties.AssemblyInfo.cs` 修改如下内容:

``` csharp
// 将下面内容
[assembly: AssemblyVersion("1.0.0.0")]
// 改成
[assembly: AssemblyVersion("1.0.0.*")]
```

2. 打开项目配置文件 `XXX.csproj`,修改如下内容:

``` xml
// 将这个配置改成 false
<Deterministic>false</Deterministic>
```

> **特别注意:**
>
> 当被引用 DLL 用于正式环境时,须将其程序集集版本号改成特定版本号,防止其它引用该 DLL 的其它库出现错误。
## 内置 Keyin 介绍

### keyin 汇总

| keyin 名称 | 作用 |
| ----------------------- | --------------------------------------------------- |
| MSTest install | 在用户配置中添加 TestMSAddin 启动加载配置 |
| MSTest uninstall | 取消启动加载 |
| MSTest test + keyin | 调用方法 |
| MSTest load | 加载其它 Dll。只有加载了的 Dll,才能调用其中的方法 |
| MSTest unload + dllName | 卸载已经加载的 dll |
| MSTest set | 设置参数 |
| keyin 名称 | 作用 |
| ------------------------ | ------------------------------------------------------------ |
| MSTest install | 在用户配置中添加 MSAddinTest 自启动配置。安装后,每次打开软件都会自动加载 MSAddinTest。 |
| MSTest uninstall | 取消自启动。 |
| MSTest load | 加载待测试的 Dll。只有加载了的 Dll,才能调用其中的方法。如果已经加载过,则等效于 reload。 |
| MSTest unload + dllName | 卸载已经加载的 dll |
| MSTest reload + dllName | 重新加载目标 dll。当修改编译后,需要调用该 keyin 进行重新加载。 |
| MSTest test + keyin/name | 调用方法。 |
| MSTest set | 设置参数 |

### MSTest set

该命令目前支持设置以下两个参数
该命令目前支持以下两个参数的设置

1. 目标 Dll 的启动时加载
1. 目标 Dll 在启动时就加载

格式:`dllName.autoLoad=true`

@@ -238,36 +265,51 @@ internal class TestClassExecutor : IMSTest_Class

格式:`dllName.autoReload=true`

当修改编译后,MSTestAddin 会自动重载目标 dll,不需要手动调用 `MSTest reload`

也可以同时设置:

```csharp
dllName.autoLoad=true,dllName.autoReload=true
MSTest set dllName.autoLoad=true,dllName.autoReload=true
```

如果后一个参数的 dll 名称与前一个是一样,则可以省略,如下:

``` csharp
dllName.autoLoad=true,autoReload=true
MSTest set dllName.autoLoad=true,autoReload=true
```

> 配置文件路径为
> 该配置的文件路径为
>
> "_USTN_HOMEROOT" 变量位置下的`MSAddinTest\config.json`

## VisualStudio Debug 流程
## 引用 DLL 更新

**调试:**
假设有一个 addin.dll,它引用了一个开发中的功能库 utils.dll,当我们修改 utils.dll 时,也希望插件可以热加载,及时反馈到调试上。

1. 启动 Microstation
2. 通过输入 keyin `MSTest load` 加载待测试 dll
3. VS 中附加进程到 Micostation 开启调试
要使引用的 Dll 变动触发热重载,需要给引用的程序集添加 AssemblyVersion 自增版本号(当然,也可以每次修改后手动修改该版本号)。

**重新修改:**
自增版本号修改方法如下:

1. 关闭调试
2. 编辑代码
3. 重新编译,重新编译后即可在 Microstation 调用编辑后的代码
4. 如果要进行 debug,重新附加到进程即可
1. 在 `Properties.AssemblyInfo.cs` 修改如下内容:

``` csharp
// 将下面内容
[assembly: AssemblyVersion("1.0.0.0")]
// 改成
[assembly: AssemblyVersion("1.0.0.*")]
```

2. 打开项目配置文件 `XXX.csproj`,修改如下内容:

``` xml
// 将这个配置改成 false
<Deterministic>false</Deterministic>
```

> **特别注意:**
>
> 当被引用 DLL 用于正式环境时,须将其程序集集版本号改成特定版本号,防止其它引用该 DLL 的其它库出现错误。

## 实现原理

@@ -292,7 +334,7 @@ dllName.autoLoad=true,autoReload=true

## UI

本插件预留了 UI 接口,但短期内不会实现。欢迎同志们 PR
本插件预留了 UI 接口,但短期内不会实现。欢迎 PR

## 开发环境

2 changes: 1 addition & 1 deletion TestAddinPlugin/TestAddin/PluginAddin.cs
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ public PluginAddin(IntPtr mdlDescriptor) : base(mdlDescriptor)

}

protected override void Init(AddIn addin)
public override void Init(AddIn addin)
{
Instance = addin;
Run(new string[] { });
2 changes: 1 addition & 1 deletion TestAddinPlugin/TestAddin/PluginKeyinFuncs.cs
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ public static void TestElement(string unparsed)

public static void TestAddin(string unparsed)
{

MessageBox.Show("我是纯 keyin,且我没有被 MSTest 标记,我被调用了");
}
}
}
19 changes: 9 additions & 10 deletions TestAddinPlugin/TestAddinPlugin.csproj
Original file line number Diff line number Diff line change
@@ -56,20 +56,15 @@
<ItemGroup>
<Reference Include="Bentley.DgnPlatformNET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4bf6c96a266e58d4, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files\Bentley\OpenRoads Designer CONNECT Edition\OpenRoadsDesigner\Bentley.DgnPlatformNET.dll</HintPath>
<HintPath>$(Microstation)\Bentley.DgnPlatformNET.dll</HintPath>
</Reference>
<Reference Include="Bentley.GeometryNET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4bf6c96a266e58d4, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files\Bentley\OpenRoads Designer CONNECT Edition\OpenRoadsDesigner\Bentley.GeometryNET.dll</HintPath>
<HintPath>$(Microstation)\Bentley.GeometryNET.dll</HintPath>
</Reference>
<Reference Include="Bentley.GeometryNET.Structs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4bf6c96a266e58d4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files\Bentley\OpenRoads Designer CONNECT Edition\OpenRoadsDesigner\Bentley.GeometryNET.Structs.dll</HintPath>
</Reference>
<Reference Include="MSAddinTest, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\sw_Bentley\OpenRoads\sw_Standards\mdlapps\MSAddinTest.dll</HintPath>
<Private>True</Private>
<HintPath>$(Microstation)\Bentley.GeometryNET.Structs.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -81,7 +76,7 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="ustation">
<HintPath>C:\Program Files\Bentley\OpenRoads Designer CONNECT Edition\OpenRoadsDesigner\ustation.dll</HintPath>
<HintPath>$(Microstation)\ustation.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
@@ -102,8 +97,12 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MSAddinTest\MSAddinTest.csproj">
<Project>{21d13145-f4b6-41d7-9ddd-0d9e4c128c09}</Project>
<Name>MSAddinTest</Name>
</ProjectReference>
<ProjectReference Include="..\MSUtils\MSUtils.csproj">
<Project>{E687EF99-6F1E-4255-A31F-F235257A9391}</Project>
<Project>{e687ef99-6f1e-4255-a31f-f235257a9391}</Project>
<Name>MSUtils</Name>
</ProjectReference>
</ItemGroup>
8 changes: 6 additions & 2 deletions TestAddinPlugin/TestClassExecutor.cs
Original file line number Diff line number Diff line change
@@ -14,9 +14,13 @@ namespace TestAddinPlugin
/// 1. 继承接口 IMSTest_Class
/// 2. 类添加特性 MSTest
/// </summary>
[MSTest("class", Description = "测试 IClassPlugin 插件")]
internal class TestClassExecutor : IMSTest_Class
[MSTest("class", Description = "测试 IClassPlugin 插件,通过 mstest test class 来调用")]
public class TestClassExecutor : IMSTest_Class
{
/// <summary>
/// 该接口为实例初始化后的调用入口
/// </summary>
/// <param name="arg"></param>
public void Execute(string arg)
{
MessageBox.Show("IClassPlugin 被调用了!");
2 changes: 1 addition & 1 deletion TestAddinPlugin/TestStaticMethodExecutor.cs
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ namespace TestAddinPlugin
/// </summary>
public class TestStaticMethodExecutor : IMSTest_StaticMethod
{
[MSTest("static")]
[MSTest("static",Description ="通过 mstest test static 来调用")]
public static object Execute(string arg)
{
MessageBox.Show("IStaticMethodPlugin 被调用了4!");