在Visual Studio扩展中包含外部.dll

本文关键字:包含外 dll 扩展 Visual Studio | 更新日期: 2023-09-27 18:14:39

我有一个使用外部库为我的visual studio扩展的问题。目前,我有我自己的NuGet服务器上我托管我的库,现在,因为我不想功能两次我提取了一些功能,我的扩展到一个现有的库。

问题是,无论何时我想使用该程序集中的任何东西,我都不能这样做,因为visual studio不包括。vsix包中的。dll。

到目前为止,我已经试过了:

  1. 使用Assets从它们的包位置包含库。这将在解决方案中创建两个项目,它们的"Include in VSIX"属性设置为true,这不起作用
  2. 包括项目,然后添加BuiltProjectOutputGroup;BuiltProjectOutputGroupDependencies;GetCopyToOutputDirectoryItems;到引用的"其他组包含在VSIX"属性,该属性不起作用
  3. 使用资产将库包含为项目,这不起作用

所以现在我在我的结束,因为没有什么似乎工作....

我找到的解决方案已经建议了我尝试过的所有步骤,但此时

我也发现这两个帖子是相同的我的问题,但这些答案不适合我,就像我说的。

在Visual Studio扩展中包含外部.dll

我找到了一种方法,它是我在这里找到的堆栈溢出的两个答案的组合。

尽管这有点俗气,但我想这是唯一可能的方法。

所以我只是使用现有的ManualAssemblyResolver并根据我的需要进行调整,结果如下:

public class ManualAssemblyResolver : IDisposable
{
    #region Attributes
    /// <summary>
    /// list of the known assemblies by this resolver
    /// </summary>
    private readonly List<Assembly> _assemblies;
    #endregion
    #region Properties
    /// <summary>
    /// function to be called when an unknown assembly is requested that is not yet kown
    /// </summary>
    public Func<ResolveEventArgs, Assembly> OnUnknowAssemblyRequested { get; set; }
    #endregion
    #region Constructor
    public ManualAssemblyResolver(params Assembly[] assemblies)
    {
        _assemblies = new List<Assembly>();
        if (assemblies != null)
            _assemblies.AddRange(assemblies);
        AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
    }
    #endregion
    #region Implement IDisposeable
    public void Dispose()
    {
        AppDomain.CurrentDomain.AssemblyResolve -= OnAssemblyResolve;
    }
    #endregion
    #region Private
    /// <summary>
    /// will be called when an unknown assembly should be resolved
    /// </summary>
    /// <param name="sender">sender of the event</param>
    /// <param name="args">event that has been sent</param>
    /// <returns>the assembly that is needed or null</returns>
    private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
    {
        foreach (Assembly assembly in _assemblies)
            if (args.Name == assembly.FullName)
                return assembly;
        if (OnUnknowAssemblyRequested != null)
        {
            Assembly assembly = OnUnknowAssemblyRequested(args);
            if (assembly != null)
                _assemblies.Add(assembly);
            return assembly;
        }
        return null;
    }
    #endregion
}

之后,我使用了一个add ExtensionManager来获取扩展的安装路径。它看起来像这样

public class ExtensionManager : Singleton<ExtensionManager>
{
    #region Constructor
    /// <summary>
    /// private constructor to satisfy the singleton base class
    /// </summary>
    private ExtensionManager()
    {
        ExtensionHomePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Definitions.Constants.FolderName);
        if (!Directory.Exists(ExtensionHomePath))
            Directory.CreateDirectory(ExtensionHomePath);
        SettingsFileFullname = Path.Combine(ExtensionHomePath, Definitions.Constants.SettingsFileName);
        InstallationPath = Path.GetDirectoryName(GetType().Assembly.Location);
    }
    #endregion
    #region Properties
    /// <summary>
    /// returns the installationPath
    /// </summary>
    public string InstallationPath { get; private set; }
    /// <summary>
    /// the path to the directory where the settings file is located as well as the log file
    /// </summary>
    public string ExtensionHomePath { get; private set; }
    /// <summary>
    /// the fullpath to the settingsfile
    /// </summary>
    public string SettingsFileFullname { get; private set; }
    #endregion
}

然后在Package的Initialize()方法中,您需要创建ManualAssemblyResolver的实例,并提供所需程序集的路径,如下所示:

    #region Attributes
    private ManualAssemblyResolver _resolver;
    #endregion
    #region Override Microsoft.VisualStudio.Shell.Package
    /// <summary>
    /// Initialization of the package; this method is called right after the package is sited, so this is the place
    /// where you can put all the initialization code that rely on services provided by VisualStudio.
    /// </summary>
    protected override void Initialize()
    {
        _resolver = new ManualAssemblyResolver(
        Assembly.LoadFrom(Path.Combine(ExtensionManager.Instance.InstallationPath, Definitions.Constants.NameOfAssemblyA)),
        Assembly.LoadFrom(Path.Combine(ExtensionManager.Instance.InstallationPath, Definitions.Constants.NameOfAssemblyB))
        );

请注意,你需要在任何其他东西甚至触及引用程序集的任何东西之前调用它,否则将抛出FileNotFoundException。

在任何情况下,这似乎对我现在工作,但我希望有一个更干净的方式来做它。因此,如果有人有更好的方法(实际上包括并查找.vsix包中的程序集的方法),请发布答案。

编辑:好了,现在我发现了真正的问题,这是一个简单的事实,dll是卫星dll(他们有他们的程序集区域性设置),所以他们不可见....