I have a host WinForm application extended with UserControls. Composition and instantiation work great on initial startup. When I close the user control, I want to assume that it should be Disposed. However, this causes a problem when I want to show the user control again.
What I want to do is return the user control to it’s original state after I ensure the object has Disposed of any resources.
Here is one of the extension user controls:
[ExportMetadata ( "ModuleName", "ContactManager" )]
[Export ( typeof ( IUserModule ) )]
partial class ucxContactManager : IUserModule
{
#region Fields
// Fields
readonly string moduleName = "ContactManager";
readonly string moduleDescription = "Contact Manager Extension Module";
// called from ucxContactManager constructor
void InitializeUserModule ( )
{
Closing += ( o, e ) => Dispose ( );
uxCloseContactForm.Click += ( o, e ) => Closing ( this, null );
}
// IUserModule Members
public event EventHandler<EventArgs> Closing = delegate { };
}
CompositionController does all the discovery and composition work, providing a method to request a specific module:
// Lazily import all IUserModule interfaces
[ImportMany ( typeof ( IUserModule ), AllowRecomposition = true )]
public IEnumerable<Lazy<IUserModule, IQueryMetadata>> Modules { get; set; }
public bool TryGetModule ( string ModuleName, out IUserModule Module )
{
var module = Modules.Where ( m => m.Metadata.ModuleName == ModuleName )
.Select ( m => m )
.FirstOrDefault ( );
if (module != null)
{ Module = module.Value; }
else
{ Module = null; }
return Module != null;
}
Now, when we find the module, assigning module.Value causes the UserControl to be initialized – the constructor is called.
When the UserControl is closed and disposed, how can I return the module to this initial state?
I think your issue is that you are setting
Moduletomodule.Value, so you are instantiating the actualIUserModulethrough theLazy<IUserModule, IQueryMetadata>instance. If you don’t need it until later on, why no setModuleto theLazy<IUserModule, IQueryMetadata>instance instead, and then create an instance of it when you need it.The other thing you may need to consider is lifetime of the part. Unless you are recomposing your
Modulescollection, you’ll only have one instance of theIUserModulebecause it is created and instantiated through theLazy<,>instance. What you may want to consider is using anExportFactory<IUserModule, IQueryMetadata>to spin up a new instance each time instead.ExportFactoryis not part of .NET 4.0 (it made into Silverlight, but not the full .NET 4.0 BCL. Glenn Block released a version of it for .NET 4, which you can get here.