繁体   English   中英

在Visual Studio扩展中加载程序集

[英]Assembly loading in Visual Studio extension

我正在编写一个Visual Studio扩展程序,我对如何以及在何时何地加载程序集感到困惑。 我所拥有的是:

我的Visual Studio扩展项目(我们称其为MyExtension )引用了多个程序集,包括一个名为Foo.dll的程序集。

MyExtension包含一个名为FooManager的类,该类将响应于单击菜单项而实例化。

实例化FooManager ,将其传递给当前解决方案中项目的输出路径,并创建一个AppDomain来加载该程序集,如下所示:

public FooManager(string assemblyPath)
{
    // The actual ApplicationBase of the current domain will be the one of VS and 
    // not of my plugin
    // We need our new AppDomain to be able to find our assemblies
    // without this even the CreateInstanceAndUnwrap will fail
    var p = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var cachePath = Path.Combine(p, "Cache");
    var pluginPath = Path.Combine(p, "Test");
    if (Directory.Exists(cachePath))
    {
        Directory.Delete(cachePath, true);
    }
    if (Directory.Exists(pluginPath))
    {
        Directory.Delete(pluginPath, true);
    }
    Directory.CreateDirectory(cachePath);
    Directory.CreateDirectory(pluginPath);
    var newPath = Path.Combine(pluginPath, Path.GetFileName(assemblyPath));
    File.Copy(assemblyPath, newPath, true);

    var setup = new AppDomainSetup()
    {
        ApplicationBase = p,
        ShadowCopyFiles = "true",
        ShadowCopyDirectories = pluginPath,
        CachePath = cachePath              
    };

    domain = AppDomain.CreateDomain("MyTest_AppDomain", AppDomain.CurrentDomain.Evidence, setup);

    // FooCollection is defined in MyExtension. but has several references
    // to things defined in Foo.dll - it used MEF to load the assembly
    // referenced by pluginPath
    collection = domain.CreateInstanceAndUnwrap(
        typeof(FooCollection).Assembly.FullName,
        typeof(FooCollection).FullName, 
        false, 
        BindingFlags.Default, 
        null, 
        new object[] { pluginPath }, null, null) as FooCollection;
}

现在, FooManager一个属性如下所示( FooInfoFoo.dll定义):

public IEnumerable<FooInfo> Spiders
{
    get
    {
        return collection.Foos.Select(s => s.Metadata);
    }
 }

但是,当我尝试访问它时,出现System.ArgumentException消息, Object type cannot be converted to target type. 我知道如果从不同位置加载同一程序集的两个副本会发生这种情况,我想最终就是这种情况,但是我不知道如何从同一位置加载它。

因此,在为此付出了很多努力之后(以上只是我的最新尝试),我想也许可以序列化为byte[] ,然后再次进行反序列化,以避免出现类型问题,因此我尝试了以下方法:

var msgBytes = collection.SerializeFooInfo();
var msg = FooInfo.DeserializeMessage(msgBytes);

我的序列化和反序列化仅使用BinaryFormatter (这些类标记为Serializable )。 序列化似乎有效,但是在反序列化上,当我到达这里时:

public static List<FooInfo> DeserializeMessage(byte[] source)
{
    using (var stream = new MemoryStream(source))
    {
        BinaryFormatter formatter = new BinaryFormatter();
        var msg = formatter.Deserialize(stream);
        return msg as List<FooInfo>;
    }
}

msg返回为空。 如果尝试使用即时窗口在调试器中运行它,则会看到Deserialize抛出了FileNotFoundException消息:

无法加载程序集'C:\\ Users \\ matt.burland \\ AppData \\ Local \\ Microsoft \\ VisualStudio \\ 14.0Exp \\ ProjectAssemblies \\ qesxy6ms01 \\ Foo.dll'

但是我不知道那条路是从哪里来的。 它不是我的扩展程序的安装位置,它是C:\\Users\\matt.burland\\AppData\\Local\\Microsoft\\VisualStudio\\14.0Exp\\Extensions\\MyCompany\\FooTools\\1.0并已设置为我的AppDomainApplicationBase并包含文件foo.dll 那么,为什么要尝试从其他神秘位置加载呢? 另一个位置似乎是动态创建的,并且仅包含foo.dll程序集。

我在Windows服务中(与此同时使用了许多相同的类)做了一些非常类似的事情,并且它工作得很好,所以这似乎是Visual Studio扩展方式的特殊之处。 有人可以在这里发光吗?

所以我认为这可能会有所帮助: http : //geekswithblogs.net/onlyutkarsh/archive/2013/06/02/loading-custom-assemblies-in-visual-studio-extensions-again.aspx

但是,如果我尝试按照建议的那样在程序包类中附加AssemblyResolve处理程序,那么它不会被调用任何有趣的东西(这并不奇怪,这不是我尝试从中加载的域),但是如果我尝试附加到我创建的新域,然后尝试以下操作:

domain.AssemblyResolve += OnAssemblyResolve;

然后它失败了,因为我的FooManager没有被标记为可序列化的。 因此,我创建了仅用于绑定AssemblyResolve的代理,但AssemblyResolve从未触发。 因此,我尝试在创建域时不设置ApplicationBase ,以为这将迫使它不得不尝试解析,但是随后我无法在创建的域中创建代理类,因为它不知道从何处加载程序集!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM