托管可扩展框架 - 当两个类实现一个接口时无法使用mef

时间:2015-05-29 13:24:46

标签: c# mef

我有一个接口,两个类实现了这个接口。在这种情况下,我无法使用MEF概念。我的代码如下。请帮我转换使用MEF。

 public interface IResultsRepository
    {
        IList<string> GetResults();
        string GetSummary();
    }

[Export(typeof(IResultsRepository))]
public class ExcelResultsRepository : IResultsRepository
{
    private readonly string filePath;
    private readonly string worksheetName;
    [ImportingConstructor]
    public ExcelResultsRepository([Import("FilePath")]string filePath, [Import("WorkSheetName")]string worksheetName)
    {
        this.filePath = filePath;
        this.worksheetName = worksheetName;
    }
    public IList<string> GetResults()
    {
    }
    public string GetSummary()
    {
    }
}

[Export(typeof(IResultsRepository))]
public class ResultsFormRepository : IResultsRepository
{
    private readonly ResultForm resultForm;
    [ImportingConstructor]
    public ResultsFormRepository([Import("ResultFormInstance")]ResultForm resultForm)
    {
        this.resultForm = resultForm;
    }
    public IList<string> GetResults()
    {

    }
    public string GetSummary()
    {
    }
}

[Export("ResultFormInstance")]
public class ResultForm
{
    public string Tables
    {
        get { return ""; }
    }

    public string Summary
    {
        get
        {
            return "";
        }
    }
}

[Export]
public class ResultsContentConverter
{
    private readonly IResultsRepository resultRepository;

    [ImportingConstructor]
    public ResultsContentConverter([Import(typeof(IResultsRepository))]IResultsRepository resultRepository)
    {
        this.resultRepository = resultRepository;
    }

    public ResultContent GetResultContent()
    {
        //logic to convert the format and return formatted object containg results and summary
    }
}

[TestFixture]
[Export]
public class ResultComapreTest
{
    [Import] 
    private ResultsContentConverter excelContentConverter;

    [Import("ResultFormConverter", typeof(IResultsRepository))]
    private ResultsContentConverter resultFormContentConverter;

    [Test]
    public void CompareResultFromResultForm()
    {
        ResultContent expectedResult;
        ResultContent actualResult;

        using (IResultsRepository excelResultsRepository = new ExcelResultsRepository(@"C:\Users\akuma211\Abhineet\Project\Sample\UnityContainerLearning\Sample\book1.xlsx", "sheet1"))
        {
            var converter = new ResultsContentConverter(excelResultsRepository);

            expectedResult = converter.GetResultContent();
        }

        using (IResultsRepository resultsRepository = new ResultsFormRepository(new ResultForm()))
        {
            var converter = new ResultsContentConverter(resultsRepository);

            actualResult = converter.GetResultContent();
        }

        Assert.AreEqual(expectedResult.Summary, actualResult.Summary);
        Assert.AreEqual(expectedResult.Tables[0].Rows.Count, actualResult.Tables[0].Rows.Count);
    }
}

在测试方法中,我应该使用MEF。请帮帮我

由于

您好我正在编辑下面的测试方法。

[Test]
        public void CompareResultFromResultForm()
        {
            ResultContent expectedResult;
            ResultContent actualResult;

            Compose();// MEF composer, that composes my ResultsContentConverter object
            //using (IResultsRepository excelResultsRepository = new ExcelResultsRepository(@"C:\Users\akuma211\Abhineet\Project\Sample\UnityContainerLearning\Sample\book1.xlsx", "sheet1"))
            //{
            //    var converter = new ResultsContentConverter(excelResultsRepository);

            //    expectedResult = converter.GetResultContent();
            //}
            expectedResult = excelContentConverter.GetResultContent();

            //using (IResultsRepository resultsRepository = new ResultsFormRepository(new ResultForm()))
            //{
            //    var converter = new ResultsContentConverter(resultsRepository);

            //    actualResult = converter.GetResultContent();
            //}
            actualResult = resultFormContentConverter.GetResultContent();

            Assert.AreEqual(expectedResult.Summary, actualResult.Summary);
            Assert.AreEqual(expectedResult.Tables[0].Rows.Count, actualResult.Tables[0].Rows.Count);
        }

我使用了importmany并按照以下方式执行了此操作

ResultContent expectedResult;
            ResultContent actualResult;

            var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var container = new CompositionContainer(catalog);
            container.ComposeExportedValue<string>("FilePath", @"C:\Users\akuma211\Abhineet\Project\Sample\UnityContainerLearning\Sample\book1.xlsx");
            container.ComposeExportedValue<string>("WorkSheetName", "sheet1");
            container.ComposeExportedValue<ResultForm>("ResultFormInstance", new ResultForm());

            container.ComposeParts(this);
            //ResultComapreTest obj = container.GetExportedValue<ResultComapreTest>();

            foreach (IResultsRepository rep in repository)
            {
                var converter = new ResultsContentConverter(rep);
                converter.GetResultContent();
            }

但我不想使用new创建ResultsContentConverter对象。 而不是foreach我使用

using (IResultsRepository excelResultsRepository = (repository.Where(rep => rep.GetType() == typeof(ExcelResultsRepository)).Select(rep => rep).First()))
            {
                var converter = new ResultsContentConverter(excelResultsRepository);

                expectedResult = converter.GetResultContent();
            }

            using (IResultsRepository resultsRepository = (repository.Where(rep => rep.GetType() == typeof(ResultsFormRepository)).Select(rep => rep).First()))
            {
                var converter = new ResultsContentConverter(resultsRepository);

                actualResult = converter.GetResultContent();
            }

            Assert.AreEqual(expectedResult.Summary, actualResult.Summary);
            Assert.AreEqual(expectedResult.Tables[0].Rows.Count, actualResult.Tables[0].Rows.Count);

1 个答案:

答案 0 :(得分:0)

当然mef会给你一个组合异常。 您将为框架提供两个相同接口的实现。 MEF如何能够检测到您想要的实现?

您可以解决此问题并使用[ImportMany],它将基本导入IResultsRepository接口的所有可用实现。

您将获得可用实施的列表,您可以循环查找要进行单元测试的实施。

有关详细信息,请参阅此页面: https://msdn.microsoft.com/de-de/library/dd460648(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/system.componentmodel.composition.importmanyattribute(v=vs.110).aspx

http://dotnetbyexample.blogspot.de/2010/04/very-basic-mef-sample-using-importmany.html

一个简单的例子: 有你的界面:

    public interface IResultsRepository
{
    IList<string> GetResults();
    string GetSummary();
}

以及实现此接口的两个类:

[Export(typeof(IResultsRepository))]
class CustomResultContainer : IResultsRepository
{
    [ImportingConstructor]
    public CustomResultContainer(IDoNothing nothing)
    {
    }

    public IList<string> GetResults()
    {
        throw new NotImplementedException();
    }

    public string GetSummary()
    {
        throw new NotImplementedException();
    }
}

[Export(typeof(IResultsRepository))]
class ResultContainerWithLogging : IResultsRepository
{
    [ImportingConstructor]
    public ResultContainerWithLogging(ILogger logger)
    {

    }

    public IList<string> GetResults()
    {
        throw new NotImplementedException();
    }

    public string GetSummary()
    {
        throw new NotImplementedException();
    }
}

请注意,构造函数彼此不同,每个类依赖于不同的接口(代表您的用例)。 Bf接口由mef注入。你可以在这里找到这个部分:

    [Export(typeof(ILogger))]
class VoidLogger : ILogger
{
    public void Log()
    {
        Console.Write("Void Logging");
    }
}

[Export(typeof(IDoNothing))]
class DoNothingStub : IDoNothing
{
    public void doNothing()
    {

    }
}

interface ILogger
{
    void Log();
}

interface IDoNothing
{
    void doNothing();
}

现在将所有这些组合在一起:

        private void startup()
    {
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly().Location);
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);

        foreach (var resultsRepository in this.repositories)
        {
            Debugger.Break();
        }
    }

    [ImportMany]
    public List<IResultsRepository> repositories { get; set; }
}

这将在irepositories列表中提供完整的两个元素,因为MEF找到了两个实现并为我注入了它们。