Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The <a href="http://mef.codeplex.com/" rel="nofollow noreferrer">Managed Extensibility Framework</a> (available through codeplex for pre-.NET-4.0, or built-in .NET 4.0 in the <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.composition(VS.100).aspx" rel="nofollow noreferrer">System.ComponentModel.Composition</a> namespace) was built for this. Say you have a <em>service</em> that can ask a user to select a wizard and then create it. It uses a wizard <em>provider</em> to create the wizards, and needs to know the name and available spells (<em>metadata</em>) for the wizards that a provider creates. You might use interfaces like these:</p> <pre><code>namespace Wizardry { using System.Collections.Generic; public interface IWizardProvider { IWizard CreateWizard(); } public interface IWizard { IMagic GetMagic(string magicWord); } public interface IWizardProviderMetadata { string Name { get; } IEnumerable&lt;string&gt; Spells { get; } } } </code></pre> <p>The wizard creation service <em>imports</em> the available wizard providers, selects one through some mechanism (user feedback in your case), and uses the provider to create the wizard.</p> <pre><code>namespace Wizardry { using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.Linq; public class UserWizardCreationService { [Import] private IEnumerable&lt;Lazy&lt;IWizardProvider, IWizardProviderMetadata&gt;&gt; WizardProviders { get; set; } public IWizard CreateWizard() { IWizard wizard = null; Lazy&lt;IWizardProvider, IWizardProviderMetadata&gt; lazyWizardProvider = null; IWizardProvider wizardProvider = null; // example 1: get a provider that can create a "White Wizard" lazyWizardProvider = WizardProviders.FirstOrDefault(provider =&gt; provider.Metadata.Name == "White Wizard"); if (lazyWizardProvider != null) wizardProvider = lazyWizardProvider.Value; // example 2: get a provider that can create a wizard that can cast the "booblah" spell lazyWizardProvider = WizardProviders.FirstOrDefault(provider =&gt; provider.Metadata.Spells.Contains("booblah")); if (lazyWizardProvider != null) wizardProvider = lazyWizardProvider.Value; // finally, for whatever wizard provider we have, use it to create a wizard if (wizardProvider != null) wizard = wizardProvider.CreateWizard(); return wizard; } } } </code></pre> <p>You can then create and <em>export</em> an arbitrary number of wizard providers with spells, and the creation service will be able to find them:</p> <pre><code>namespace Wizardry { using System.ComponentModel.Composition; [Export(typeof(IWizardProvider))] [Name("White Wizard")] [Spells("booblah", "zoombar")] public class WhiteWizardProvider : IWizardProvider { public IWizard CreateWizard() { return new WhiteWizard(); } } [Export(typeof(IWizardProvider))] [Name("White Wizard")] [Spells("zoogle", "xclondon")] public class BlackWizardProvider : IWizardProvider { public IWizard CreateWizard() { return new BlackWizard(); } } } </code></pre> <p>Of course you'll need to implement the wizards as well.</p> <pre><code>namespace Wizardry { using System; public class WhiteWizard : IWizard { public IMagic GetMagic(string magicWord) { throw new NotImplementedException(); } } public class BlackWizard : IWizard { public IMagic GetMagic(string magicWord) { throw new NotImplementedException(); } } } </code></pre> <p>To keep things clean, this code uses a custom <code>NameAttribute</code> and <code>SpellsAttribute</code> as a much cleaner form of exporting metadata than <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.exportmetadataattribute(VS.100).aspx" rel="nofollow noreferrer"><code>ExportMetadataAttribute</code></a>:</p> <pre><code>namespace Wizardry { using System; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] public abstract class MultipleBaseMetadataAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public abstract class SingletonBaseMetadataAttribute : Attribute { } public sealed class NameAttribute : SingletonBaseMetadataAttribute { public NameAttribute(string value) { this.Name = value; } public string Name { get; private set; } } public sealed class SpellsAttribute : MultipleBaseMetadataAttribute { public SpellsAttribute(params string[] value) { this.Spells = value; } public string[] Spells { get; private set; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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