Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are two ways to do what you're looking to do:</p> <ul> <li>Create a factory and import all necessary parts into the factory, then pass that into the constructor of the classes. For this to work you must make your factory aware of the different classes that implement the <code>IBarViewModel</code> interface and the parts they require for instantiation, or use reflection to get them in some list.</li> </ul> <p><b>BarViewModelFactory:</b></p> <pre><code>[Export(typeof(IBarViewModelFactory))] public class BarViewModelFactory : IBarViewModelFactory { [Import] private IServiceA ServiceA { get; set; } [Import] private IServiceB ServiceB { get; set; } // val is some metadata value to help decide which class to instantiate. public IBarViewModel CreateBarViewModel(string val, string text) { IBarViewModel result = null; try { // Select using metadata... if (String.Equals(val, "x", StringComparison.OrdinalIgnoreCase)) result = new SuperBarViewModel(ServiceA, ServiceB, text); else result = new BarViewModel(ServiceA, text); } catch (Exception ex) { ... } finally { ... } return result; } } </code></pre> <p><b>IBarViewModel implementations:</b></p> <pre><code>public sealed class BarViewModel : ViewModelBase, IBarViewModel { public BarViewModel(IServiceA svcA, string text) { ServiceA = svcA; // Do something with text, etc... } private IServiceA ServiceA { get; set; } } public sealed class SuperBarViewModel : ViewModelBase, IBarViewModel { public BarViewModel(IServiceA svcA, IServiceB svcB, string text) { ServiceA = svcA; ServiceB = svcB; // Do something with text, etc... } private IServiceA ServiceA { get; set; } private IServiceB ServiceB { get; set; } } </code></pre> <hr> <ul> <li>Alternatively, you might be able to take advantage of the <code>ExportFactory&lt;T, TMetadata&gt;</code>. It is part of <a href="http://msdn.microsoft.com/en-us/library/ff382771(v=vs.95).aspx" rel="nofollow">MEF (Silverlight)</a>, <a href="http://mef.codeplex.com/" rel="nofollow">MEF Codeplex library (ver 2)</a>, and <a href="http://msdn.microsoft.com/en-us/library/ff382771(v=vs.110).aspx" rel="nofollow">Microsoft.Net 4.5</a>. Note that an ExportFactory cannot instantiate a class and pass parameters into the constuctor, so you're forced to use the <code>text</code> by setting a property (or calling a method) after the instance has been created. Also, here is some information on the <a href="http://mef.codeplex.com/wikipage?title=Exports%20and%20Metadata" rel="nofollow">Using ExportMetadataAttribute</a>.</li> </ul> <p><b>BarViewModelFactory:</b></p> <pre><code>[Export(typeof(IBarViewModelFactory))] public class BarViewModelFactory : IBarViewModelFactory { [ImportMany] private IEnumerable&lt;ExportFactory&lt;IBarViewModel, IBarViewModelMetadata&gt;&gt; Factories { get; set; } // val is some metadata value to help decide which class to return. public IBarViewModel CreateBarViewModel(string val, string text) { IBarViewModel result = null; try { result = Factories.Single(x =&gt; String.Equals(x.Metadata.Value, val, StringComparison.OrdinalIgnoreCase)) .CreateExport() .Value; result.Text = text; } catch (Exception ex) { ... } finally { ... } return result; } } </code></pre> <p><b>IBarViewModel implementations:</b></p> <pre><code>[ExportMetadata(typeof(IBarViewModel, ""))] public sealed class BarViewModel : ViewModelBase, IBarViewModel { [Import] private IServiceA ServiceA { get; set; } public string Text { get; set; } } [ExportMetadata(typeof(IBarViewModel, "x"))] public sealed class SuperBarViewModel : ViewModelBase, IBarViewModel { [Import] private IServiceA ServiceA { get; set; } [Import] private IServiceB ServiceB { get; set; } public string Text { get; set; } } </code></pre> <hr> <p>For both scenarios, I chose to use a string text to differentiate between <code>SuperBarViewModel</code> ("x") and <code>BarViewModel</code> (""), but you can choose practically whatever metadata you want to help select one.</p> <p><b>Usage Example (works for both scenarios):</b></p> <pre><code>[Export] public sealed class SomeClass { [Import] private IBarViewModelFactory BarViewModelFactory { get; set; } public void SomeMethod() { // Get the "Super" version by passing in "x" (metadata). var barVM = BarViewModelFactory.CreateBarViewModel("x", "my text"); // etc... } } </code></pre> <hr> <p>Obviously, there is a lot more you can do on top of this, such as creating your own custom <code>ExportAttribute</code> instead of using the default <code>ExportMetadataAttribute</code> for exports with metadata. This will allow you to create more complex metadata. Also, <code>SatisfyImports</code>/<code>SatisfyImportsOnce</code> is something to look into if you need it. Basically, you can expand on this answer to customize your solution.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload