能否不使用FullName从GAC加载程序集?

20

我知道如何从文件名和全局程序集缓存中加载程序集。 由于我的.msi文件将一个dll项目放入全局程序集缓存中,所以我想知道是否可能从全局程序集缓存中加载它而不知道完整名称(我的意思是只使用程序集名称,甚至是dll文件名),因为我需要从另一个项目中加载此程序集。


4
这就是 Assembly.LoadWithPartialName() 的设计初衷。自 2.0 版本以来,因为该方法已经过时,所以被标记为 [Obsolete]。 - Hans Passant
2个回答

22

这里有一段代码可以实现这个功能,还有一个例子:

    string path = GetAssemblyPath("System.DirectoryServices");
    Assembly.LoadFrom(path);

请注意,如果您需要特定的处理器架构,由于它支持部分名称,您可以编写这样的内容:

    // load from the 32-bit GAC
    string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=X86");

    // load from the 64-bit GAC
    string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=AMD64");

这是实现:

    /// <summary>
    /// Gets an assembly path from the GAC given a partial name.
    /// </summary>
    /// <param name="name">An assembly partial name. May not be null.</param>
    /// <returns>
    /// The assembly path if found; otherwise null;
    /// </returns>
    public static string GetAssemblyPath(string name)
    {
        if (name == null)
            throw new ArgumentNullException("name");

        string finalName = name;
        AssemblyInfo aInfo = new AssemblyInfo();
        aInfo.cchBuf = 1024; // should be fine...
        aInfo.currentAssemblyPath = new String('\0', aInfo.cchBuf);

        IAssemblyCache ac;
        int hr = CreateAssemblyCache(out ac, 0);
        if (hr >= 0)
        {
            hr = ac.QueryAssemblyInfo(0, finalName, ref aInfo);
            if (hr < 0)
                return null;
        }

        return aInfo.currentAssemblyPath;
    }


    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
    private interface IAssemblyCache
    {
        void Reserved0();

        [PreserveSig]
        int QueryAssemblyInfo(int flags, [MarshalAs(UnmanagedType.LPWStr)] string assemblyName, ref AssemblyInfo assemblyInfo);
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct AssemblyInfo
    {
        public int cbAssemblyInfo;
        public int assemblyFlags;
        public long assemblySizeInKB;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string currentAssemblyPath;
        public int cchBuf; // size of path buf.
    }

    [DllImport("fusion.dll")]
    private static extern int CreateAssemblyCache(out IAssemblyCache ppAsmCache, int reserved);

哇!看起来很复杂!我本来在寻找更简单的东西,但我认为你提出的解决方案肯定是实现这一目标的最佳选择!谢谢,如果有必要,我会尝试它的! - metalcam
干得好,Simon。我已经按照Code Project上的说明将这个答案用于TypeResolver类:http://www.codeproject.com/Articles/641878/Resolving-an-unreferenced-partial-type-name-using - John O

-2

是的,这就是GAC的全部意义。运行时会首先查找GAC,而不是当前目录。


1
谢谢您提供的详细信息,但我想知道是否有什么技巧可以执行例如Assembly.Load("myAssembly")而不是Assembly.Load("myAssembly, Version=xxxxx, PublicKeyToken=xxxxxx")。在我看来,这似乎是不可能的,但现在我正在寻找了解我的MSI中主要输出的程序集名称,并将其放入app.config中,以便在代码中动态获取程序集名称。 - metalcam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接