【问题标题】:C# Reflection Load "System" assembly without FQN没有 FQN 的 C# 反射加载“系统”程序集
【发布时间】:2009-10-01 21:54:59
【问题描述】:

我想使用 Assembly.ReflectionOnlyLoad() 从一些 .NET 系统程序集(如 System、System.Windows.Forms 等)中提取 MemberInfos。现在我理解它的方式,我必须提供程序集的完全限定名称(包括版本信息和所有这些)或路径。但是,我希望我的代码不依赖于特定版本。相反,我只想提供部分名称(“System.Windows.Forms”),然后应该加载该程序集的最新版本。如果存在,另一种方法是 GAC 中的程序集路径。

我想一定有办法,因为 Visual Studio 似乎也可以做到这一点。当您查看参考部分中的项目文件时,只能指定“System.Windows.Forms”并且不能指定进一步的版本信息,但 VS 需要在项目中引用正确的程序集版本。有谁知道我怎么能做到这一点?

非常感谢!

【问题讨论】:

  • 如果您在 Visual Studio 中查看属性以供参考,您将看到程序集版本号
  • 系统应该已经以非反射状态加载。

标签: c# reflection gac


【解决方案1】:

ReflectionOnlyLoad() 最终以true 为forIntrospection 参数调用私有nLoad() 方法。另一方面,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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多