我想使用Assembly.ReflectionOnlyLoad()从某些.NET系统程序集(如System,System.Windows.Forms等)中提取MemberInfos。现在我解决它的方式,我必须提供程序集的完全限定名称(包括版本信息和所有)或路径。但是,我希望我的代码不依赖于特定版本。相反,我只想提供部分名称(“System.Windows.Forms”),然后应加载此程序集的最新版本。如果存在,则替代方案是GAC中程序集的路径。
我想必须有一种方法,因为Visual Studio似乎也是这样做的。当您查看参考部分中的项目文件时,只能指定“System.Windows.Forms”并且不能指定其他版本信息,但VS会在项目中引用正确的程序集版本。有谁知道我怎么能做到这一点?
非常感谢!
答案 0 :(得分:0)
ReflectionOnlyLoad()
最终使用nLoad()
为true
参数调用私有forIntrospection
方法。另一方面,具有所需程序集查找行为的LoadWithPartialName()
也会使用不同的参数集(nLoad()
和false
)委托给forIntrospection
。用内省复制部分调用是一个简单的反思问题。 :)
更新:实际上并不那么简单。如果nLoad()
失败,我们需要调用私有EnumerateCache()
,然后调用其他InternalLoad()
。以下适用于我的机器:
[Test]
public void TestReflectionOnlyLoadWithPartialName()
{
var l = ReflectionOnlyLoadWithPartialName("System.Windows.Forms");
Assert.IsTrue(l.ReflectionOnly);
}
public Assembly ReflectionOnlyLoadWithPartialName(string partialName)
{
return ReflectionOnlyLoadWithPartialName(partialName, null);
}
public Assembly ReflectionOnlyLoadWithPartialName(string partialName, Evidence securityEvidence)
{
if (securityEvidence != null)
new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
AssemblyName fileName = new AssemblyName(partialName);
var assembly = nLoad(fileName, null, securityEvidence, null, null, false, true);
if (assembly != null)
return assembly;
var assemblyRef = EnumerateCache(fileName);
if (assemblyRef != null)
return InternalLoad(assemblyRef, securityEvidence, null, true);
return assembly;
}
private Assembly nLoad(params object[] args)
{
return (Assembly)typeof(Assembly)
.GetMethod("nLoad", BindingFlags.NonPublic | BindingFlags.Static)
.Invoke(null, args);
}
private AssemblyName EnumerateCache(params object[] args)
{
return (AssemblyName)typeof(Assembly)
.GetMethod("EnumerateCache", BindingFlags.NonPublic | BindingFlags.Static)
.Invoke(null, args);
}
private Assembly InternalLoad(params object[] args)
{
// Easiest to query because the StackCrawlMark type is internal
return (Assembly)
typeof(Assembly).GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
.First(m => m.Name == "InternalLoad" && m.GetParameters()[0].ParameterType == typeof(AssemblyName))
.Invoke(null, args);
}