MEF中的设计模式策略

时间:2015-10-07 14:59:57

标签: .net design-patterns mef

我有返回实现特定接口的对象的方法。取决于参数方法返回不同的对象。所有都实现了相同的接口,所以我可以在方法外的接口上使用相同的方法,如Execute()。 这个解决方案迫使我避免使用MEF。我怎样才能一次使用这两种解决方案?从MEF导入构造函数并在不同的类中隔离不同的策略?

以下是一个示例代码:

[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();
        }
        //(...)
    }  

总结: 我喜欢将不同的策略分为不同的类,在 UkCrowdMessageProcessor DefaultCrowdMessageProcessorAdapter 。但是在新的这类( ICrowdMessageProcessor )中,我还需要使用 ImportingConstructor 。我该怎么办?

1 个答案:

答案 0 :(得分:0)

解决方案1: 使用 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;
    }
}