视觉工作室外接程序的依赖项注入

本文关键字:依赖 注入 程序 工作室 视觉 | 更新日期: 2023-09-27 18:32:02

我正在开发一个Visual Studio加载项,该加载项在您的项目中接受SQL查询,播放请求并为结果生成C#包装类。我想做一个最简单的依赖项注入,其中使用我的外接程序的项目提供了一个类,该类可以提供项目的数据库连接字符串等。

此接口在我的加载项中定义...

[Serializable]
public interface IDesignTimeQueryProcessing
{
    public string ConnectionString { get; }
    ...
}

问题:如何定义和实例化具体实现,然后从加载项使用它?

进展?

上面的接口在加载项中定义。我在目标项目中创建了对外接程序的引用,编写了具体实现,并将此类的名称放在目标项目 web.config 中。现在,我需要从外接程序加载目标项目以使用我的具体类。

如果我使用 Assembly.Load()...

var userAssembly = Assembly.LoadFrom(GetAssemblyPath(userProject));
IQueryFirst_TargetProject iqftp = (IQueryFirst_TargetProject)Activator.CreateInstance(userAssembly.GetType(typeName.Value));

我可以成功加载我的类,但我锁定了目标程序集,无法再编译目标项目。

如果我创建临时应用程序域...

AppDomain ad = AppDomain.CreateDomain("tmpDomain", null, new AppDomainSetup { ApplicationBase = Path.GetDirectoryName(targetAssembly) });
byte[] assemblyBytes = File.ReadAllBytes(targetAssembly);
var userAssembly = ad.Load(assemblyBytes);

我在来电广告上收到未找到文件异常。Load(),即使我的 dll 的字节在内存中。

如果我使用 CreateInstanceFromAndUnwrap()...

AppDomain ad = AppDomain.CreateDomain("tmpDomain", null, new AppDomainSetup { ApplicationBase = Path.GetDirectoryName(targetAssembly) });
IQueryFirst_TargetProject iqftp = (IQueryFirst_TargetProject)ad.CreateInstanceFromAndUnwrap(targetAssembly, typeName.Value);

我得到一个

无效投射异常。"无法将透明代理转换为类型 QueryFirst.IQueryFirst_TargetProject"

这让我觉得我很接近?为什么显式强制转换在 Assembly.Load() 中工作正常,但在新创建的 AppDomain 中加载同一程序集时失败?

视觉工作室外接程序的依赖项注入

我假设您的加载项将以某种方式触发以开始使用SQL查询。

我建议您在加载项中捆绑一个单独的.exe文件,并在其中进行处理。

原因如下:

  1. 就个人而言,我在AppDomain上遇到了很多问题,类似于您在文件锁定和临时域中遇到的头痛。 您可能会遇到的另一个问题是,一旦将程序集加载到 AppDomain 中,就无法卸载。 通过使用单独的进程(完成后会死亡),您不必担心问题。
  2. 根据要支持的项目类型,这些项目将具有依赖项。 如果您可以将独立.exe指向目录(即 bin 目录),则管理对依赖 dll 的引用将容易得多。
  3. 如果你挂接到Visual Studio的生成事件(DTE.Events.BuildEvents.OnBuildBegin),你可以终止你的进程并释放dll文件上的锁。 或者,您可以先让您的流程制作副本。
  4. 使用独立文件进行测试/调试要容易得多。 你不需要担心通过附加到Visual Studio(如何调试Vsix项目)来尝试调试。

您可以使用以下方法来启动/终止进程:

  • Process.Start
  • Process.Kill

我认为您可以通过 VSIX 包的引用剖析直接从 VSIX 添加项目引用控制台项目的输出。 因此,您可能需要执行一些自定义 MSBuild 才能将.exe包含在 VSIX 文件中。

包含它后,您可以找到.exe,因为它应该与执行 VSIX (Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 位于同一路径中,我会将路径传递给加载的项目的 bin 目录。


顺便说一句,这不是依赖注入。 如果你想在VS扩展中使用DI,你可以使用任何你想要的框架,但我认为MEF是原生支持的。 就个人而言,我更喜欢Ninject。 在 Package 类中定义您的Kernel,并使用它来加载您的顶级类。