Possible Duplicate:
Help needed with unloading .DLL’s from AppDomain - Still not working even with ShadowCopy
In my project I use the MEF framework to provide extensibility; The main program can be extended by another Lib.dll class library.
The problem is that I need to swap this Lib.dll with another one WITHOUT CLOSING the main program.
So how can I unload this Lib.dll to swap it ?
Update
the main program is in form:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace SimpleCalculator3
{
public interface ICalculator
{
String Calculate(String input);
}
public interface IOperation
{
int Operate(int left, int right);
}
public interface IOperationData
{
Char Symbol { get; }
}
[Export(typeof(IOperation))]
[ExportMetadata("Symbol", '+')]
class Add : IOperation
{
public int Operate(int left, int right)
{
return left + right;
}
}
[Export(typeof(IOperation))]
[ExportMetadata("Symbol", '-')]
class Subtract : IOperation
{
public int Operate(int left, int right)
{
return left - right;
}
}
[Export(typeof(ICalculator))]
class MySimpleCalculator : ICalculator
{
[ImportMany]
IEnumerable<Lazy<IOperation, IOperationData>> operations;
public String Calculate(String input)
{
int left;
int right;
Char operation;
int fn = FindFirstNonDigit(input); //finds the operator
if (fn < 0) return "Could not parse command.";
try
{
//separate out the operands
left = int.Parse(input.Substring(0, fn));
right = int.Parse(input.Substring(fn + 1));
}
catch
{
return "Could not parse command.";
}
operation = input[fn];
foreach (Lazy<IOperation, IOperationData> i in operations)
{
if (i.Metadata.Symbol.Equals(operation)) return i.Value.Operate(left, right).ToString();
}
return "Operation Not Found!";
}
private int FindFirstNonDigit(String s)
{
for (int i = 0; i < s.Length; i++)
{
if (!(Char.IsDigit(s[i]))) return i;
}
return -1;
}
}
class Program
{
private CompositionContainer _container;
[Import(typeof(ICalculator))]
public ICalculator calculator;
private Program()
{
//An aggregate catalog that combines multiple catalogs
var catalog = new AggregateCatalog();
//Adds all the parts found in the same assembly as the Program class
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
//catalog.Catalogs.Add(new DirectoryCatalog("C:\\Users\\SomeUser\\Documents\\Visual Studio 2010\\Projects\\SimpleCalculator3\\SimpleCalculator3\\Extensions"));
//Create the CompositionContainer with the parts in the catalog
_container = new CompositionContainer(catalog);
//Fill the imports of this object
try
{
this._container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
static void Main(string[] args)
{
Program p = new Program(); //Composition is performed in the constructor
String s;
Console.WriteLine("Enter Command:");
while (true)
{
s = Console.ReadLine();
Console.WriteLine(p.calculator.Calculate(s));
}
}
}
}
and the extending Lib.dll is in form
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
namespace ExtendedOperations {
[Export(typeof(SimpleCalculator3.IOperation))]
[ExportMetadata("Symbol", '%')]
public class Mod : SimpleCalculator3.IOperation
{
public int Operate(int left, int right)
{
return left % right;
}
}
}
that is it, I want to dynamically change code in Lib.dll and build it while the main program is running
You can load your files in another AppDomain, which you can unload when you don't need it.
AppDomainSetup ads = new AppDomainSetup();
ads.PrivateBinPath = Path.GetDirectoryName("C:\\some.dll");
AppDomain ad2 = AppDomain.CreateDomain("AD2", null, ads);
ProxyDomain proxy = (ProxyDomain)ad2.CreateInstanceAndUnwrap(typeof(ProxyDomain).Assembly.FullName, typeof(ProxyDomain).FullName);
bool ok = proxy.LoadDll("C:\\some.dll");
AppDomain.Unload(ad2);
public class ProxyDomain : MarshalByRefObject
{
public bool LoadDll(string assemblyPath)
{
Assembly myDLL = Assembly.LoadFile(assemblyPath);
//use your dll here
}
}