Strongly Typed Metadata
지난 포스트의 [MEF] 7. Exports and Metadata를 통해 Export 의 Contract 에 Metadata 를 제공하는 방법을 알아보았습니다.
MetadataAttribute 을 선언하여 Export 의 Metadata 를 제공하는 방법입니다.
[Export(typeof(IMessageSender))]
[ExportMetadata("SenderType", "Email")]
[ExportMetadata("Logging", true)]
public class EmailMessageSender : IMessageSender
{
public void Say()
{
Console.WriteLine("Import EmailMessageSender");
}
} |
Export 에 Metadata 를 제공해 주어서 무척 고맙지만, 위의 방법처럼 MetadataAttribute 를 선언하는 방법을 사용하기에 그다지 내키지 않는 구석이 있습니다.
아무래도 아래와 같은 이유 때문이겠죠?
l 메타데이터의 타입 불안정
l 빌드 시 오류를 해결이 어려움
l 사용상 모든 키값을 외우기 어렵고, 오타 발생 위험
위의 이유 때문에 Metadata 를 사용하기 위해 강력한 타입을 원하게 될 것입니다. 그리고 강력한 타입의 Metadata 를 사용하길 권장 드립니다.
Declaring Strongly Typed Metadata
Attribute 을 상속받아 Export 의 Metadata 를 Strongly Typed 으로 확장시키는 방법입니다.
아래의 Stringly Typed Metadata 를 위해 Attribute 클래스를 만드는 소스 코드 입니다.
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class MessageSenderTypeAttribute : Attribute
{
public MessageSenderTransport Transport { get; set; }
public bool IsSecure { get; set; }
public MessageSenderTypeAttribute() { }
public MessageSenderTypeAttribute(MessageSenderTransport transport)
: this(transport, false)
{
}
public MessageSenderTypeAttribute(MessageSenderTransport transport, bool isSecure)
{
this.Transport = transport;
this.IsSecure = IsSecure;
}
}
public enum MessageSenderTransport
{
Email,
Phone,
Sms
} |
Strongly Typed Metadata 를 위한 Attribute 클래스를 완성하였으면, 이것을 그대로 ExportAttribute 과 함께 추가적으로 선언하면 됩니다.
그리고 ExportAttribute 을 선언한 코드에 위의 Attribute 특성을 부여합니다. 아래는 그 소스 코드의 일부입니다.
[Export(typeof(IMessageSender))]
[MessageSenderType(MessageSenderTransport.Email)]
public class EmailMessageSender : IMessageSender
{
public void Say()
{
Console.WriteLine("Import EmailMessageSender");
}
}
[Export(typeof(IMessageSender))]
[MessageSenderType(MessageSenderTransport.Phone, true)]
public class PhoneMessageSneder : IMessageSender
{
public void Say()
{
Console.WriteLine("Import PhoneMessageSneder");
}
}
[Export(typeof(IMessageSender))]
[MessageSenderType(Transport=MessageSenderTransport.Sms, IsSecure=true)]
public class SmsMessageSender : IMessageSender
{
public void Say()
{
Console.WriteLine("Import SmsMessageSender");
}
} |
그렇다면 아래와 같이 Metadata 를 Strongly Typed 으로 질의(Query) 할 수 있게 됩니다.
아래의 소스 코드는 지난 포스트의 소스 전체 소스 코드를 참고하십시오.
foreach (var export in program.Sender)
{
if ((MessageSenderTransport)export.Metadata["Transport"] == MessageSenderTransport.Sms)
{
export.GetExportedObject().Say();
if ((bool)export.Metadata["IsSecure"] == true)
{
Console.WriteLine("Security message");
}
}
} |
위의 소스 코드 실행 결과는 원하던 결과대로 다음과 같습니다.
[그림1] Strongly Typed 질의 결과
하지만 아직도 문제는 남아 있는 것 같아 보이네요. Strongly Typed 으로 Export Metadata 를 선언하였지만 여전히 질의(Query) 과정은 똑같은 문제점을 가지고 있습니다.
l 메타데이터의 질의(Query) 과정의 타입 불안정
l 빌드 시 오류를 해결이 어려움
l 사용상 모든 키값을 외우기 어렵고, 오타 발생 위험
More Strongly Typed Metadata Query
Metadata 를 질의(Query) 하기 위해 MEF 는 보다 강력하게 Import 하는 방법을 제공해 줍니다. 확장된 MetadataAttribute 에 인터페이스(Interface) 를 구현하도록 하여 Import 시에 인터페이스(Interface) 를 통한 Metadata 를 질의(Query) 하는 방법입니다.
우선 Attribute 에 사용되는 프로퍼티를 인터페이스로 선언합니다.
public interface IMessageSenderTypeAttribute
{
bool IsSecure { get; }
MessageSenderTransport Transport { get; }
} |
단, 여기에서 반드시 Getter 만 선언하셔야 합니다. Setter 를 선언하시면 MEF 는 Setter 프로퍼티로 인해 유효하지 않는 Attribute 으로 인식하여 예외를 발생하게 됩니다.
아래의 소스 코드는 Metadata Attribute 클래스에 위의 인터페이스를 구현한 코드 입니다.
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class MessageSenderTypeAttribute : Attribute, IMessageSenderTypeAttribute
{
public MessageSenderTransport Transport { get; set; }
public bool IsSecure { get; set; }
public MessageSenderTypeAttribute() { }
public MessageSenderTypeAttribute(MessageSenderTransport transport)
: this(transport, false)
{
}
public MessageSenderTypeAttribute(MessageSenderTransport transport, bool isSecure)
{
this.Transport = transport;
this.IsSecure = IsSecure;
}
} |
이제 Export 의 MetadataView 로 질의할 수 있도록 MetadataView 의 인터페이스를 알려주도록 해야 합니다.
[Import(typeof(IMessageSender))]
ExportCollection<IMessageSender, IMessageSenderTypeAttribute> Sender { get; set; }
아래의 소스 코드는 MetadataView 를 통해 Strongly Typed 으로 Export Metadata 를 질의(Query) 하는 소스 코드 입니다.
[Import(typeof(IMessageSender))]
ExportCollection<IMessageSender, IMessageSenderTypeAttribute> Sender { get; set; }
static void Main(string[] args)
{
Program program = new Program();
program.Run();
foreach (var export in program.Sender)
{
if (export.MetadataView.Transport == MessageSenderTransport.Email)
{
export.GetExportedObject().Say();
}
}
} |
'Managed Extensibility Framework' 카테고리의 다른 글
[MEF] 10. Querying the CompositionContainer (0) | 2009.05.18 |
---|---|
[MEF] 9. Recomposition (1) | 2009.04.19 |
[MEF] 7. Exports and Metadata (0) | 2009.04.16 |
[MEF] 6. Lazy Exports (0) | 2009.04.13 |
[MEF] 5. Catalog 사용 (0) | 2009.04.09 |