visual studio 加载项的依赖注入

Dependency injection for a visual studio add-in

我正在开发一个 visual studio 加载项,它在您的项目中接受 SQL 查询,播放请求并为结果生成一个 C# 包装器 class。我想做一个尽可能简单的依赖注入,其中使用我的加载项的项目提供一个 class,它可以提供项目的数据库连接字符串,等等。

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

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

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

有进展吗?

上面的接口是在加载项中定义的。我已经在目标项目中创建了对加载项的引用,编写了具体实现,并将这个class的名称放在了目标项目web.config中。现在我需要从加载项加载目标项目以使用我的具体 class.

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

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

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

If I create a temporary app domain...

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

我在调用 ad.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);

我得到一个

InvalidCastException. "Unable to cast transparent proxy to type QueryFirst.IQueryFirst_TargetProject"

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

我假设您的 add-in 将以某种方式被触发,以便开始使用 SQL 查询。

我建议您将一个单独的 .exe 文件与您的 add-in 捆绑在一起,然后在其中进行处理。

原因如下:

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

您可以使用以下方法start/kill处理:

我认为您可以通过参考 Anatomy of a VSIX Package 直接从您的 VSIX 加载项项目中引用控制台项目的输出。否则,您可能需要执行一些自定义 MSBuild 操作才能将 .exe 包含在 VSIX 文件中。

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


顺便说一句,这不是 Dependency Injection. If you want to use DI inside a VS Extension, you can use whatever framework you'd like, but I think MEF is natively supported. Personally, I prefer Ninject。在 Package class 中定义你的 Kernel 并用它来加载你的顶层 class.