如何加载旧版本的.NET程序集?

时间:2011-10-31 21:13:56

标签: c# .net

我有一个引用.NET 4.0程序集的WPF / C#应用程序。但是,在应用程序中是一个文本编辑器,需要显示与.NET 3.5程序集绑定的C#intellisense。因此,我希望能够在运行时加载适当的.NET 3.5程序集。但是,当我尝试使用时:

Assembly.Load()
Assembly.LoadFile()
Assembly.LoadFrom()

我总是从GAC获得最新版本。阅读他们的MSDN页面,看起来不幸的是设计。

我尝试按照stack overflow post中提出的解决方案进行操作。但是,链接的网页解决方案不起作用,远程处理过程似乎有点矫枉过正。有没有人知道在运行时加载旧.NET程序集的更好和/或更简单的方法?

5 个答案:

答案 0 :(得分:1)

默认情况下,您无法在.NET Framework版本4上加载为以前版本的.NET框架创建的程序集。

但是,有一个配置属性允许:http://msdn.microsoft.com/en-us/library/bbx34a2h.aspx

将以下行放在app.config文件中:

<configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true|false" > 
    </startup>
</configuration>

默认情况下,这是有原因的,但我认为它应该适合您的使用。

答案 1 :(得分:1)

之前我已经完成了这项工作,虽然来自GAC中没有的程序集:我从字节数组中加载了Mine,但我可以很容易地拥有相同程序集的不同版本。

解决方案是处理AppDomain的AssemblyResolve事件,以便确保返回所需的程序集。在你的情况下,这可能相当简单,因为你只关心做这个特定的调用。其余的时间你采取默认设置,甚至根本不处理。

一个可能的例子可能是:

public DoSomething()
{
    //Add the handler
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve

    //Load your assembly...
}

private System.Reflection.Assembly CurrentDomain_AssemblyResolve(Object sender, ResolveEventArgs e)
{
    foreach (System.Reflection.Assembly a In AppDomain.CurrentDomain.GetAssemblies())
    {
       if (a.FullName == <<The one you need>>) return a
    }
}

这很粗糙,但它会给出一个过程的概念 - 你处理assemblylfolve,并返回你需要的东西。处理程序的内容可能会有所不同,因为我不确定您的程序集是否会出现在CurrentDomain.GetAssemblies()列表中。

可能会有更多微妙的解决方案,可以为您处理GAC版本。

注意:这在.Net 3.5中使用,而不是4,但确实适用于不同版本。您可能需要@Jean的解决方案来在4中加载3.5个程序集。

答案 2 :(得分:1)

您可以在app.config或web.config中使用AssemblyBinding属性,以适当的方式。

例如,我正在与Matlab接口,所以我需要这个......

<loadFromRemoteSources enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="MWArray" publicKeyToken="E1D84A0DA19DB86F" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.10.0.0" />
        </dependentAssembly>
    </assemblyBinding>

因为我使用的Matlab引擎在使用运行时的不同副本的机器上编译(有些疯狂)。

您应该能够修改此代码以满足您的需求。

答案 3 :(得分:0)

我发现的一个部分解决方案是使用Assembly.ReflectionOnlyLoadFrom()。此方法正确加载旧版本的程序集,尽管程序集已加载到仅反射上下文中,这意味着您无法在程序集中执行代码。虽然这不是真正的程序集加载,但它确实启用了我正在处理的大多数智能感知场景。

一个挥之不去的问题是mscorlib。当尝试使用从ReflectionOnlyLoadFrom返回的程序集时,对于较旧版本的mscorlib,会抛出异常:“System.TypeLoadException:无法从程序集'mscorlib加载类型'System.Object',版本= 4.0.0.0,Culture = neutral ,PublicKeyToken = b77a5c561934e089'因为父母不存在。“

答案 4 :(得分:0)

我使用ReflectionOnlyLoadFrom()来解决此问题,以便在只读模式下加载我需要的任何版本的程序集,仅用于反射。当你不能为mscorlib做这个事实时(你可以要求2.0,但你会从调用中得到4.0),我通过过滤根据我需要的版本返回的类型来处理这个问题。毕竟,在这种模式下,你只能使用反射来检查DLL中的类型,而不是用它们做任何其他事情,因此你可以轻松地过滤掉根据需要返回的类型列表。

以下是我到目前为止从mscorlib 4.0中过滤掉的类型,以便在预期使用旧版本的mscorlib时一切正常:

    /// <summary>
    /// Types to be hidden from .NET mscorlib 4.0 for older versions.
    /// </summary>
    protected static readonly HashSet<Type> HideMscorlib4Types = new HashSet<Type>
        {
            // The Action delegates with 0, 2, 3, 4 type parameters were moved from System.Core 3.5 to mscorlib for 4.0
            typeof(Action), typeof(Action<,>), typeof(Action<,,>), typeof(Action<,,,>),

            // The Func delegates with 1 to 5 type parameters were moved from System.Core 3.5 to mscorlib for 4.0
            typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), typeof(Func<,,,>), typeof(Func<,,,,>),

            // Other types moved from System.Core 3.5 to mscorlib 4.0
            typeof(TimeZoneInfo),

            // Hide various types that were new in mscorlib 4.0
            typeof(Tuple)
        };