I have a WPF/C# application that references .NET 4.0 assemblies. However, within the application is a text editor that needs to display C# intellisense tied to .NET 3.5 asse
By default, you cannot load assemblies made for previous versions of the .NET framework on the .NET framework version 4.
However, there is a configuration attribute that allows that: http://msdn.microsoft.com/en-us/library/bbx34a2h.aspx
Put the following lines in your app.config file:
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true|false" >
</startup>
</configuration>
There are reasons why this is not active by default, but I believe that it should be appropriate for your use.
You can use the AssemblyBinding property in your app.config or web.config, whichever is appropriate.
For instance, I'm interfacing with Matlab, so I need this...
<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>
Because the Matlab engine I work with is compiled (some crazy how) on a machine using a different copy of the runtime.
You should be able to modify this code to suit your needs.
I solved this problem using ReflectionOnlyLoadFrom() to load assemblies of whatever version that I need in read-only mode for use with reflection only. When it comes to the fact that you can't do this for mscorlib (you can ask for 2.0, but you'll get 4.0 back from the call), I handled this by filtering the types returned based upon the version that I needed. After all, in this mode, you can only inspect the types in the DLL using reflection, and not really do anything else with them, so you can easily filter the list of types returned as needed.
Here are the types that I've filtered out of mscorlib 4.0 so far so that everything works when an older version of mscorlib is expected:
/// <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)
};
I've done this before, albeit from assemblies that weren't in the GAC: Mine were being loaded from byte arrays, but I could easily have different versions of the same assembly.
The solution was to handle the AssemblyResolve event of the AppDomain, so that you can ensure that the assembly you require is returned. In your case this could be fairly simple, as you only care when doing this particular invocation. The rest of the time you'd take the default and not handle the even at all.
A possible example might be:
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
}
}
This is pretty crude, but it'll give a idea of the process - you handle the assemblyresolve, and return what you need. The contents of your handler will likely be different as I'm not sure your assembly will be present in the CurrentDomain.GetAssemblies()
list.
There are probably more subtle examples of assmeblyresolve out there that will handle GAC versions for you.
Notes: This was used in .Net 3.5, not 4, but did work for different versions. You may need @Jean's solution to load 3.5 assemblies in 4.
One partial solution I discovered is to use Assembly.ReflectionOnlyLoadFrom(). This method correctly loads older versions of assemblies, although the assembly is loaded into a reflection-only context, meaning you can't execute code in the assembly. While this isn't a true assembly load, it does enable most of the intellisense scenario I'm working on.
The one lingering problem is mscorlib. When trying to use the assembly returned from ReflectionOnlyLoadFrom, for an older version of mscorlib, an exception is thrown: "System.TypeLoadException: Could not load type 'System.Object' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' because the parent does not exist."