I am trying to stop my application locking DLLs in my MEF plugin directory so that I can overwrite the assemblies at runtime (note I'm not actually trying to have MEF reload them on the fly, at the next app start is fine, i just dont want to have to stop the app to do the copy)
I am trying to do this by creating a shadow copied app domain for my mef loaded assemblies as below:
[Serializable]
public class Composer:IComposer
{
private readonly string _pluginPath;
public Composer(IConfigurePluginDirectory pluginDirectoryConfig)
{
_pluginPath = pluginDirectoryConfig.Path;
var setup = new AppDomainSetup();
setup.ShadowCopyFiles = "true"; // really??? is bool not good enough for you?
var appDomain = AppDomain.CreateDomain(AppDomain.CurrentDomain.FriendlyName + "_PluginDomain", AppDomain.CurrentDomain.Evidence, setup);
appDomain.DoCallBack(new CrossAppDomainDelegate(DoWorkInShadowCopiedDomain));
}
private void DoWorkInShadowCopiedDomain()
{
// This work will happen in the shadow copied AppDomain.
var catalog = new AggregateCatalog();
var dc = new DirectoryCatalog(_pluginPath);
catalog.Catalogs.Add(dc);
Container = new CompositionContainer(catalog);
}
public CompositionContainer Container { get; private set; }
}
and then access my MEF component catalog via the CompositionContainer on this class. However the composition container seems to only be initialised inside the shadowcopy domain (which makes sense) and this means that its null in my application domain. I was just wondering if theres a better way to do this or some way to cross domain query to get my MEF components
If you don't want to follow the solution from Dan Bryant and zync, you could create a shell application that simply executes your application in a new AppDomain
.
An approach would be:
AppDomain
, enable shadow copying and if you wish, specify the directory where shadow copying will be enabled. AppDomain.ExecuteAssembly
to call your current application.If instead of an application you have a class library you can try the following:
Add the following interface to the new class library project:
public interface IRemoteLoader
{
void Load();
void Unload();
}
Add an implementation of this interface to your class library that needs to execute in a new AppDomain. In the Load
and Unload
methods you should add code to perform initialization and cleanup respectively. Make the class derive from MarshalByRefObject
. This is needed for .NET Remoting to create proxy objects on both AppDomains.
After you create the new AppDomain, use CreateInstanceAndUnwrap
to create an instance of the loader class from step 3.
Use the Load
and Unload
on the object created from step 4.
This will be enough if you do not fine-grained control and simply starting/stopping is enough.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With