5

我想使用反射在 GAC 中动态加载最新安装的程序集版本。

到目前为止,我已经找到了多种工作方法来实现这一点,但它们都有其特定的缺点。

最简单的解决方案是使用该Assembly.LoadWithPartialName()方法。但这种方法自 .NET Framework 2 起就已过时:

var assembly = Assembly.LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime");

另一种可能性是使用Assembly.Load()(如过时警告所建议的那样)并在 try/catch 块中使用其完全限定的程序集名称调用不同的程序集版本,以获取最新的安装版本。这需要维护,看起来很脏:

Assembly assembly = null;

try
{
    assembly = Assembly.Load("Microsoft.WindowsAzure.ServiceRuntime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
}
catch (FileNotFoundException) { }

try
{
    assembly = Assembly.Load("Microsoft.WindowsAzure.ServiceRuntime, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
}
catch (FileNotFoundException) { }

最后但并非最不重要的一点是,我在 SO 上找到了 另一个解决方案Assembly.LoadFrom(),使用该方法,然后基本上导入程序集管理器模块fusion.dll来计算最新版本的路径。对于这样一个“简单”的任务来说,这似乎太过分了。

如果不使用过时的方法、使用魔术字符串或调用非托管代码创建维护地狱,难道没有更好的解决方案来实现这一点吗?

提前致谢!

4

1 回答 1

3

Fusion.dll ...呃。我会找到您的目标框架版本并枚举所有气体目录,然后根据根程序集名称简单地查询它们,这样您唯一的魔术字符串就是程序集名称。然后,使用 Assembly.ReflectionOnlyLoadFrom 静态方法比较版本,直到找到最新版本,然后使用带有适当文件路径参数的 Assembly.Load 方法。除非您给予应用程序适当的信任,否则使用单击一次下载可能会遇到问题。

// List of all the different types of GAC folders for both 32bit and 64bit
// environments.
List<string> gacFolders = new List<string>() { 
    "GAC", "GAC_32", "GAC_64", "GAC_MSIL", 
    "NativeImages_v2.0.50727_32", 
    "NativeImages_v2.0.50727_64" 
};

foreach (string folder in gacFolders)
{
    string path = Path.Combine(@"c:\windows\assembly", folder);
    if(Directory.Exists(path))
    {
        Response.Write("<hr/>" + folder + "<hr/>");

        string[] assemblyFolders = Directory.GetDirectories(path);
        foreach (string assemblyFolder in assemblyFolders)
        {
            Response.Write(assemblyFolder + "<br/>");
        }
    }
}

请参阅此处有关堆栈溢出的其他答案。我用它成功地枚举了 gac。

于 2012-07-26T03:21:05.517 回答