Showing posts with label Assembly. Show all posts
Showing posts with label Assembly. Show all posts

Thursday, April 7, 2011

Loading different versions of same .Net assembly

In my previous post I described how to load assemblies from a sub folder. You may run into a scenario when assemblies in root folder are referring a particular version of assembly while assemblies in subfolder are referring to a different version of same assembly. Assume this assembly (Lets call it SomeAssembly.dll) is placed in root folder and version no of this is 1.0, now if assemblies in subfolder need to refer 2.0 version of this assembly. So put 2.0 version of this assembly in the subfolder and instruct assembly resolve mechanism to load the assemlies from subfolders if it failed to load automatically. Below code shows how to do it:


static void Main(string[] args)
{
   AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
   string locFormat = Environment.CurrentDirectory + "\\{0}\\" + args.Name.Split(',')[0] + ".dll";
   foreach (string subPath in AppDomain.CurrentDomain.RelativeSearchPath.Split(';'))
  {
     string filePath = string.Format(locFormat, subPath);
     if (File.Exists(filePath) && AssemblyName.GetAssemblyName(filePath).FullName == args.Name)
     {
        return Assembly.LoadFile(filePath);
     }
   }
 return null; // Failed to load
}

Note that this also applicable when using binding redirect is not a solution and you want different components with in you application to use a different version of a private assembly, you can put each of those different version in to seperate subfolders(as assembly file name is same only one assembly can be put in a single folder). Use above code and add these subfolders into probing path as described here.

Monday, March 28, 2011

Automatically load .Net assemblies from sub-folder

If you need to put a set of assemblies in a sub folder of output directory, you can set that path as private path of the appdomain. Here is a way to do it and also make it configurable so that a new path can be added easily with recompiling.

Add below entry to App.config
<configuration>
  <configSections>
     <section name="AdditionalProbingPaths" type="System.Configuration.SingleTagSectionHandler"></section>
  </configSections>
</configuration>
<AdditionalProbingPaths Path1="FolderPath" Path2="AnotherPath" Path3="BlahBlah" />


Now in your Main Method write below code.
public static void Main(string[] args_)
{
  var section = (Hashtable)System.Configuration.ConfigurationManager.GetSection("AdditionalProbingPaths");
  foreach (string path in section.Values)
  {
     AppDomain.CurrentDomain.AppendPrivatePath(path);
   }
}

Now when any assembly is to be resolved by run time it will also look at these path. Easy!

Type based templating

            <DataTemplate DataType="{x:Type vm:SampleViewModel}">                 <DataTemplate.Resources>       ...