XAML.cz Magazín moderních technologií založených na XAML

Coproject – demo RIA aplikace krok za krokem, díl 5.

Napsáno pro Silverlight od Augustin Šulc [03.02.2011]

V tomto díle použijeme metadata pro upřesnění modulů. Nezapomeňte, že zdrojové kódy Coprojectu si můžete stáhnout z Codeplexu.

Metadata

Jistě jste si povšimli, že moduly se v aplikaci nezobrazují v pevně daném pořadí. To není přesně to, co bychom od aplikace očekávali, bude tedy nutné specifikovat pořadí modulů. K tomu využijeme metadata. Více o metadatech v MEFu si můžete přečíst zde.

Nejsnazší možností, jak přidat metadata k exportovaným komponentám, je použít atribut [ExportMetadata]. S ním by upravený HomeViewModel vypadal následovně:

[Export(typeof(IModule))]
[ExportMetadata("Order", 10)]
public class HomeViewModel : Screen, IModule

Ostatní moduly se pak liší jen v čísle Order. Dále je nutné upravit konstruktor ShellViewModelu, aby místo kolekce objektů IModule očekával kolekci typů Lazy<IModule, IModuleMetadata>. Tím MEF dodá nejenom referenci na požadovanou komponentu (v tomto případě navíc “Lazy” způsobem, tj. vlastní instance se vytvoří až poté, co je odkaz poprvé opravdu využit), ale také metadata. Více o typu Lazy si můžete přečíst zde.

Pojďme tedy vytvořit metadata – do nové složky /Framework/ přidejte interface IModuleMetadata:

namespace Coproject.Framework
{
	public interface IModuleMetadata
	{
		int Order { get; }
	}
}

Teď už můžeme upravit i zmíněný konstruktor v ShellViewModelu:

[ImportingConstructor]
public ShellViewModel([ImportMany]IEnumerable<Lazy<IModule, IModuleMetadata>> moduleHandles)
{
	var modules = from h in moduleHandles orderby h.Metadata.Order select h.Value;
	Items.AddRange(modules);
}

To je vše – spusťte aplikaci. Můžete zkoušet měnit čísla Order u jednotlivých modulů a sledovat, jak se podle toho mění jejich pořadí v hlavní menu aplikace.

Typovaná metadata

Ačkoliv výše zmíněné řešení splňuje to, co od něj požadujeme, je možné, že stejně jako já nemáte rádi textové konstanty přímo v kódu (“Order”). Při psaní se člověk může často překlepnout a tyto chyby se pak velice obtížně odhalují. Ideální by tedy bylo, aby se případný překlep objevil již při kompilaci. K tomu si budeme muset napsat vlastní atribut pro exportní metadata. Do složky Framework přidejte novou třídu “ExportModuleAttribute”. Projekt by teď měl vypadat takto:

Implementace nové třídy bude následující:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class)]
public class ExportModuleAttribute : ExportAttribute, IModuleMetadata
{
	public int Order { get; private set; }

	public ExportModuleAttribute(int order)
		: base(typeof(IModule))
	{
		Order = order;
	}
}

Jak vidíte, rozšířili jsme původní atribut [Export] o property Order. Jelikož se tento atribut bude používat pouze na moduly, můžeme v konstruktoru hned upřesnit, že budeme exportovat interface IModule. Důležitý je první řádek, který MEFu říká, že z tohoto atributu si má také vytáhnout doplňující metadata k exportu.

Nyní už můžeme původní řádky označující moduly:

[Export(typeof(IModule))]
[ExportMetadata("Order", 10)]

Nahradit tímto:

[ExportModule(10)]
public class HomeViewModel : Screen, IModule

Upravte takto všechny moduly a zkuste spustit Coproject.

PartCreationPolicy

Když už mluvíme o MEFu, jistě vás zajímá, jak se MEF zachová, když je jedna komponenta importována na více místech – bude vždycky vytvořena nová instance, nebo všichni “obdrží” tu stejnou? Odpověď není jednoznačná, záleží to totiž na konfiguraci. Tato konfigurace může proběhnout na dvou místech: buď u exportu

[ExportModule(10)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeViewModel : Screen, IModule

nebo u importu

[Import(typeof(IShell), RequiredCreationPolicy=CreationPolicy.Shared)]
public IShell Shell { get; set; }

CreationPolicy může nabývat tří hodnot:
Shared – MEF vrátí vždy stejnou instanci (tudíž se komponenta chová jako singleton)
NonShared – MEF vždy vytvoří pro každý import novou instanci
Any – není definováno, záleží na druhém konci kontraktu (export/import). Toto je výchozí nastavení a pokud není specifikováno ani na jedné straně kontraktu, chová se jako Shared.

Více se o tomto tématu můžete dočíst zde. Pokud vás MEF zaujal, rozhodně doporučuji přečíst tyto stránky: MEF for Beginner a MEF Programming Guide.

Komentáře

ukládám komentář, vyčkejte prosím..
  1. Buďte první, kdo napíše komentář.

@xamlcz

  • RT @jvanrhyn: XAML, It's a bit like olives. Takes a while to get used to. But once you're used to it. It is actually pretty good. <3 XAML
  • RT @moser_christian: WPF Inspector 0.9.7 is released. It supports .NET 3.5 and 4.0 The project is now open source and available on CodeP ...
  • Jeff Handley oznámil vydání WCF RIA Services v.1.0 SP1 RTM http://bit.ly/gOgckn ke stažení na http://bit.ly/gVAXdK
  • jedna výzva pro Brno. Byl někdo z vás na přednášce o RIA v MS Akvárku? Dejte o sobě vědět. Děkuji
  • také jste uvažovali o tom, že zkusíte na projekt použít Caliburn Micro nebo naopak Prism 4? A co tak obojí, šlo by to nebo ne? Již brzy