MEF 中的设计模式策略
Design pattern strategy in MEF
我有 returns 对象实现特定接口的方法。取决于参数方法 return 不同的对象。全部实现相同的接口,因此我可以在方法外部的接口上使用相同的方法,如 Execute()。
这个解决方案迫使我避免使用 MEF。如何同时使用这两种解决方案?从 MEF 导入构造函数并在单独的 classes?
中隔离不同的策略
这是一个示例代码:
[Export(typeof(ICrowdMessageProcessorFactory))]
public class CrowdMessageProcessorFactory : ICrowdMessageProcessorFactory
{
private readonly IDefaultCrowdRequestAnalyzer _defaultProcessor;
[ImportingConstructor]
public CrowdMessageProcessorFactory(IDefaultCrowdRequestAnalyzer defaultProcessor)
{
_defaultProcessor = defaultProcessor;
}
public Metadata PayloadMetadata { get; private set; }
public ICrowdMessageProcessor Create(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
PayloadMetadata = Metadata.Create(request);
var marketRegion = PayloadMetadata?.GetMarketRegion();
switch (marketRegion)
{
case MarketRegion.Uk:
return new UkCrowdMessageProcessor();
}
return new DefaultCrowdMessageProcessorAdapter(request, fireUtcDateTime, _defaultProcessor);
}
}
下面是方法的使用
[ImportingConstructor]
public CrowdResponseAnalyzer(
ICrowdMessageProcessorFactory processorFactory)
{
_processorFactory = processorFactory;
}
public void Execute(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
Guard.ArgumentNotNull(request, "request");
try
{
ICrowdMessageProcessor processor = _processorFactory.Create(request, fireUtcDateTime);
processor.Execute();
}
//(...)
}
总结:
我喜欢将不同的策略分离到不同的 class,这里是 UkCrowdMessageProcessor 和 DefaultCrowdMessageProcessorAdapter。但是在新的这种 class (ICrowdMessageProcessor) 中,我还需要使用 ImportingConstructor。我该怎么做?
解决方案一:
使用 CompositionContainer 及其方法 GetExportedValue。
当它看起来时:
public ICrowdMessageProcessor Create(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
PayloadMetadata = Metadata.Create(request);
var marketRegion = PayloadMetadata?.GetMarketRegion();
switch (marketRegion)
{
case MarketRegion.Uk:
return _cc.GetExportedValue<UkCrowdMessageProcessor>();
}
return PrepareDefaultCrowdMessageProcessor(request, fireUtcDateTime);
}
private ICrowdMessageProcessor PrepareDefaultCrowdMessageProcessor(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
var processor = _cc.GetExportedValue<DefaultCrowdMessageProcessorAdapter>();
processor.Initialize(request, fireUtcDateTime, _defaultProcessor);
return processor;
}
解决方案 2:使用 ServiceLocator 和 GetInstance
解决方案 3:从设计的角度来看,这是唯一正确的解决方案。
[Export(typeof(ICrowdMessageProcessorFactory))]
public class CrowdMessageProcessorFactory : ICrowdMessageProcessorFactory
{
private readonly IDefaultCrowdRequestAnalyzer _defaultProcessor;
private readonly UkCrowdMessageProcessor _ukCrowdMessageProcessor;
private readonly DefaultCrowdMessageProcessorAdapter _defaultCrowdMessageProcessor;
[ImportingConstructor]
public CrowdMessageProcessorFactory(
IDefaultCrowdRequestAnalyzer defaultProcessor,
UkCrowdMessageProcessor ukCrowdMessageProcessor,
DefaultCrowdMessageProcessorAdapter defaultCrowdMessageProcessor)
{
_defaultProcessor = defaultProcessor;
_ukCrowdMessageProcessor = ukCrowdMessageProcessor;
_defaultCrowdMessageProcessor = defaultCrowdMessageProcessor;
}
public Metadata PayloadMetadata { get; private set; }
public ICrowdMessageProcessor Create(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
PayloadMetadata = Metadata.Create(request);
var marketRegion = PayloadMetadata?.GetMarketRegion();
switch (marketRegion)
{
case MarketRegion.Uk:
return _ukCrowdMessageProcessor;
}
return PrepareDefaultCrowdMessageProcessor(request, fireUtcDateTime);
}
private ICrowdMessageProcessor PrepareDefaultCrowdMessageProcessor(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
_defaultCrowdMessageProcessor.Initialize(request, fireUtcDateTime, _defaultProcessor);
return _defaultCrowdMessageProcessor;
}
}
我有 returns 对象实现特定接口的方法。取决于参数方法 return 不同的对象。全部实现相同的接口,因此我可以在方法外部的接口上使用相同的方法,如 Execute()。 这个解决方案迫使我避免使用 MEF。如何同时使用这两种解决方案?从 MEF 导入构造函数并在单独的 classes?
中隔离不同的策略这是一个示例代码:
[Export(typeof(ICrowdMessageProcessorFactory))]
public class CrowdMessageProcessorFactory : ICrowdMessageProcessorFactory
{
private readonly IDefaultCrowdRequestAnalyzer _defaultProcessor;
[ImportingConstructor]
public CrowdMessageProcessorFactory(IDefaultCrowdRequestAnalyzer defaultProcessor)
{
_defaultProcessor = defaultProcessor;
}
public Metadata PayloadMetadata { get; private set; }
public ICrowdMessageProcessor Create(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
PayloadMetadata = Metadata.Create(request);
var marketRegion = PayloadMetadata?.GetMarketRegion();
switch (marketRegion)
{
case MarketRegion.Uk:
return new UkCrowdMessageProcessor();
}
return new DefaultCrowdMessageProcessorAdapter(request, fireUtcDateTime, _defaultProcessor);
}
}
下面是方法的使用
[ImportingConstructor]
public CrowdResponseAnalyzer(
ICrowdMessageProcessorFactory processorFactory)
{
_processorFactory = processorFactory;
}
public void Execute(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
Guard.ArgumentNotNull(request, "request");
try
{
ICrowdMessageProcessor processor = _processorFactory.Create(request, fireUtcDateTime);
processor.Execute();
}
//(...)
}
总结: 我喜欢将不同的策略分离到不同的 class,这里是 UkCrowdMessageProcessor 和 DefaultCrowdMessageProcessorAdapter。但是在新的这种 class (ICrowdMessageProcessor) 中,我还需要使用 ImportingConstructor。我该怎么做?
解决方案一: 使用 CompositionContainer 及其方法 GetExportedValue。 当它看起来时:
public ICrowdMessageProcessor Create(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
PayloadMetadata = Metadata.Create(request);
var marketRegion = PayloadMetadata?.GetMarketRegion();
switch (marketRegion)
{
case MarketRegion.Uk:
return _cc.GetExportedValue<UkCrowdMessageProcessor>();
}
return PrepareDefaultCrowdMessageProcessor(request, fireUtcDateTime);
}
private ICrowdMessageProcessor PrepareDefaultCrowdMessageProcessor(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
var processor = _cc.GetExportedValue<DefaultCrowdMessageProcessorAdapter>();
processor.Initialize(request, fireUtcDateTime, _defaultProcessor);
return processor;
}
解决方案 2:使用 ServiceLocator 和 GetInstance
解决方案 3:从设计的角度来看,这是唯一正确的解决方案。
[Export(typeof(ICrowdMessageProcessorFactory))]
public class CrowdMessageProcessorFactory : ICrowdMessageProcessorFactory
{
private readonly IDefaultCrowdRequestAnalyzer _defaultProcessor;
private readonly UkCrowdMessageProcessor _ukCrowdMessageProcessor;
private readonly DefaultCrowdMessageProcessorAdapter _defaultCrowdMessageProcessor;
[ImportingConstructor]
public CrowdMessageProcessorFactory(
IDefaultCrowdRequestAnalyzer defaultProcessor,
UkCrowdMessageProcessor ukCrowdMessageProcessor,
DefaultCrowdMessageProcessorAdapter defaultCrowdMessageProcessor)
{
_defaultProcessor = defaultProcessor;
_ukCrowdMessageProcessor = ukCrowdMessageProcessor;
_defaultCrowdMessageProcessor = defaultCrowdMessageProcessor;
}
public Metadata PayloadMetadata { get; private set; }
public ICrowdMessageProcessor Create(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
PayloadMetadata = Metadata.Create(request);
var marketRegion = PayloadMetadata?.GetMarketRegion();
switch (marketRegion)
{
case MarketRegion.Uk:
return _ukCrowdMessageProcessor;
}
return PrepareDefaultCrowdMessageProcessor(request, fireUtcDateTime);
}
private ICrowdMessageProcessor PrepareDefaultCrowdMessageProcessor(InsertCrowdsourcingEventRequest request, DateTime fireUtcDateTime)
{
_defaultCrowdMessageProcessor.Initialize(request, fireUtcDateTime, _defaultProcessor);
return _defaultCrowdMessageProcessor;
}
}