2011-01-10 11 views
13

Tengo el siguiente ExportMetaData atributos establecidos en mi clase:¿Cómo se establece ExportMetaData con múltiples valores, así como un único atributo w/custom?

[Export(typeof(IDocumentViewer))] 
    [ExportMetadata("Name", "MyViewer")] 
    [ExportMetadata("SupportsEditing", true)] 
    [ExportMetadata("Formats", DocFormat.DOC, IsMultiple = true)] 
    [ExportMetadata("Formats", DocFormat.DOCX, IsMultiple = true)] 
    [ExportMetadata("Formats", DocFormat.RTF, IsMultiple = true)] 

También tengo una interfaz que soporta:

public interface IDocumentViewerMetaData { 
    /// <summary> 
    /// Gets the format. 
    /// </summary> 
    /// <value>The format.</value> 
    IEnumerable<DocFormat> Formats { get; } 
    /// <summary> 
    /// Gets the name of the viewer 
    /// </summary> 
    /// <value>The name.</value> 
    string Name { get; } 
    /// <summary> 
    /// Gets a value indicating whether this viewer supports editing 
    /// </summary> 
    /// <value><c>true</c> if [supports editing]; otherwise, <c>false</c>.</value> 
    bool SupportsEditing { get; } 
    } 

Y por supuesto mi ImportMany:

[ImportMany(typeof(IDocumentViewer))] 
public IEnumerable<Lazy<IDocumentViewer, IDocumentViewerMetaData>> _viewers { get; set; } 

lo que yo gustaría hacer es utilizar una clase de atributo de tipo fuerte en lugar de usar el atributo ExportMetaData. No he encontrado una manera de hacer esto al tiempo que también soporto valores únicos (Name, SupportsEditing, en el ejemplo anterior).

preveo hacer algo similar al siguiente (o lo que se sugiere como mejor):

[Export(typeof(IDocumentViewer))] 
[DocumentViewerMetadata(Name = "MyViewer")] 
[DocumentViewerMetadata(SupportsEditing = true)] 
[DocumentViewerMetadata(Format = DocFormat.DOC)] 
[DocumentViewerMetadata(Format = DocFormat.DOCX)] 

estoy bastante seguro de que hay una manera de hacer esto, es que no he encontrado la manera correcta conecta los puntos. :)

Respuesta

17

Puede subclase el ExportAttribute con su propia aplicación, y se adorna con una MetadataAttribute para permitir MEF para utilizar sus propiedades para proyectar el proxy de metadatos que utiliza durante la composición:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property), 
MetadataAttribute] 
public class ExportDocumentViewerAttribute : ExportAttribute, IDocumentViewerMetadata 
{ 
    public ExportDocumentViewer(string name, bool supportsEditing, params DocFormat[] formats) 
    : base(typeof(IDocumentViewer)) 
    { 
    if (string.IsNullOrEmpty(name)) 
     throw new ArgumentException("Export requires a name", "name"); 

    Name = name; 
    SupportsEditing = supportsEditing; 
    Formats = formats ?? Enumerable.Empty<DocFormat>(); 
    } 

    public string Name { get; private set; } 

    public bool SupportsEditing { get; private set; } 

    public IEnumerable<DocFormat> Formats { get; private set; } 
} 

[ExportDocumentViewer("Word", true, DocFormat.DOC, DocFormat.DOCX)] 
public WordDocumentViewer : IDocumentViewer 
{ 
    // Stuff 
} 

Nota se en realidad no es necesario decorarlo con su contrato IDocumentViewerMetadata, ya que MEF lo proyectará independientemente, solo lo prefiero para que sepa si realizo cambios en el contrato de metadatos, que mi atributo de exportación personalizado se ajusta.

+0

Matthew - ¡gracias! Entiendo los cambios que hizo y realmente los prefiero, menos atributos para aplicar a las clases, así como algunos tipos adicionales de seguridad (implementación de la interfaz). Además, ahora sé lo que me faltaba en cuanto a poder pasar múltiples elementos ... params []! Estaba tan cerca de tu solución, pero perdí ese pequeño punto. Muchas gracias por su excelente respuesta. –

Cuestiones relacionadas