C# C“反射荷载”;系统“;没有FQN的程序集

C# C“反射荷载”;系统“;没有FQN的程序集,c#,reflection,gac,C#,Reflection,Gac,我想使用Assembly.ReflectionOnlyLoad()从一些.NET系统程序集(如system、system.Windows.Forms等)提取MemberInfos。现在,按照我理解它的方式,我必须提供程序集的完全限定名(包括版本信息等)或路径。但是,我希望我的代码不依赖于特定的版本。相反,我只想提供部分名称(“System.Windows.Forms”),然后加载此程序集的最新版本。另一种选择是GAC中的程序集路径(如果存在) 我想一定有办法,因为VisualStudio似乎也能

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

我想一定有办法,因为VisualStudio似乎也能做到这一点。在“引用”部分中查看项目文件时,只能指定“System.Windows.Forms”,而不能指定其他版本信息,但是VS会在项目中引用正确的程序集版本。有人知道我怎样才能做到这一点吗

非常感谢

ReflectionOnlyLoad()
最终使用
true
for introspection
参数调用private
nLoad()
方法。另一方面,
LoadWithPartialName()
,它具有所需的程序集查找行为,还使用一组不同的参数委托给
nLoad()。通过内省复制部分调用是一个简单的反思问题。:)

更新:其实并没有那么简单。如果
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);
}
ReflectionOnlyLoad()
最终使用
true
for introspection
参数调用private
nLoad()
方法。另一方面,
LoadWithPartialName()
,它具有所需的程序集查找行为,还使用一组不同的参数委托给
nLoad()。通过内省复制部分调用是一个简单的反思问题。:)

更新:其实并没有那么简单。如果
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);
}

如果查看visual studio中引用的属性,您将看到程序集版本号系统应已在非反射状态下加载。如果查看visual studio中引用的属性,您将看到程序集版本号系统应已在非反射状态下加载。