C # Reflection Load "System" without FQN

I want to use Assembly.ReflectionOnlyLoad () to retrieve MemberInfos from some .NET system assemblies like System, System.Windows.Forms, etc. Now, as I found it, I have to provide the full assembly name (including version information and all) or path. However, I want my code to not rely on a specific version. Instead, I want to provide only a partial name ("System.Windows.Forms") and then download a new version of that assembly. An alternative would be the build path in the GAC, if one exists.

I guess there must be a way as Visual Studio seems to do this as well. When you look at the project file in the referenced section, you can only specify "System.Windows.Forms" and no additional version information, but VS accepts the correct assembly version to reference in the project. Does anyone know how I can do this?

Thank you so much!

+2


source to share


1 answer


ReflectionOnlyLoad()

will end up calling the private nLoad()

method true

for the parameter forIntrospection

. On the other hand, LoadWithPartialName()

which has the desired build behavior, you also delegate nLoad()

with a different set of arguments (and false

for forIntrospection

). Replicating a partial invocation using introspection is a simple matter of reflection. :)

Update: It's actually not that easy. If it nLoad()

fails, we need to call private EnumerateCache()

and then another InternalLoad()

. The following works on my machine:



[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);
}

      

0


source







All Articles