I am trying to create a POC with mef where i have the requirement to load dll dynamically in an all ready running project , for this i have created one console application project and a class Library
project .
the code for console application project is as follows-
namespace MefProjectExtension
{
class Program
{
DirectoryCatalog catalog = new DirectoryCatalog(@"D:\MefDll", "*.dll");
[Import("Method1", AllowDefault = true, AllowRecomposition = true)]
public Func<string> method1;
static void Main(string[] args)
{
AppDomainSetup asp = new AppDomainSetup();
asp.ShadowCopyFiles = "true";
AppDomain sp = AppDomain.CreateDomain("sp",null,asp);
string exeassembly = Assembly.GetEntryAssembly().ToString();
BaseClass p = (BaseClass)sp.CreateInstanceAndUnwrap(exeassembly, "MefProjectExtension.BaseClass");
p.run();
}
}
public class BaseClass : MarshalByRefObject
{
[Import("Method1",AllowDefault=true,AllowRecomposition=true)]
public Func<string> method1;
DirectoryCatalog catalog = new DirectoryCatalog(@"D:\MefDll", "*.dll");
public void run()
{
FileSystemWatcher sw = new FileSystemWatcher(@"D:\MefDll", "*.dll");
sw.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.Size;
sw.Changed += onchanged;
CompositionContainer container = new CompositionContainer(catalog);
container.ComposeParts(this);
Console.WriteLine(this.method1());
sw.EnableRaisingEvents = true;
Console.Read();
}
void onchanged(object sender, FileSystemEventArgs e)
{
catalog.Refresh();
Console.WriteLine(this.method1());
}
}
}
the library project which satisfy import looks as follow-
namespace MefLibrary
{
public interface IMethods
{
string Method1();
}
public class CallMethods : IMethods
{
[Export("Method1")]
public string Method1()
{
return "Third6Hello";
}
}
}
once i compile the library project(MefLibrary) and put the dll in D:\MefDll location and run the console application for first time i will see the output as
Third6hello on screen
but now if i change the implementation of method1 and make it return “third7hello” build MEF Library project and replace at D:\MefDll while my console app is running the onchanged handler even after calling catalog refresh prints
Third6hello on screen rather than third7hello
Whether anyone knows what is the reason for this , if yes please help.
DirectoryCatalog.Refreshwill only add new or remove existing assemblies. It will not update an assembly. A crude workaround is:DirectoryCatalog.Refresh. This will remove the part(s) contained in the assembly.DirectoryCatalog.Refresh. This will add the updated part(s) contained in the assembly.Note:
AssemblyVersionAttribute). This is needed because when parts are removed using theDirectoryCatalog.Refreshthe actual assembly will not be unloaded. Assemblies can only be unloaded when the whole application domain is unloaded. So ifDirectoryCatalog.Refreshfinds a new assembly it will create anAssemblyCatalogusing the assembly filepath.AssemblyCatalogwill then callAssembly.Loadto load the assembly. But this method will not load an assembly that has the sameAssemblyName.FullNamewith an already loaded assembly.CompositionOption.IsThreadSafeflag.As I mentioned this is a workaround. Another approach would be to download MEF’s source code and use DirectoryCatalog.cs as a guideline for your own directory catalog implementation.