Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从MEF容器未实例化的对象导出部件 介绍_C#_Mef - Fatal编程技术网

C# 如何从MEF容器未实例化的对象导出部件 介绍

C# 如何从MEF容器未实例化的对象导出部件 介绍,c#,mef,C#,Mef,ClassSessionModel是一个提供多种服务的服务定位器(我将在将来详细阐述我的系统架构,但现在我需要这样做) 代码 我将以下代码部分编辑为简短、自包含、正确(可编译)的示例(SSCCE): 使用系统; 使用System.ComponentModel.Composition; 使用System.ComponentModel.Composition.Hosting; 命名空间控制台应用程序1 { 内部课程计划 { 私有静态void Main(字符串[]args) { var session

Class
SessionModel
是一个提供多种服务的服务定位器(我将在将来详细阐述我的系统架构,但现在我需要这样做)

代码 我将以下代码部分编辑为简短、自包含、正确(可编译)的示例(SSCCE):

使用系统;
使用System.ComponentModel.Composition;
使用System.ComponentModel.Composition.Hosting;
命名空间控制台应用程序1
{
内部课程计划
{
私有静态void Main(字符串[]args)
{
var sessionModel=新sessionModel(3);
//第一种情况(见下文):
var compositionContainer=新的compositionContainer();
//第二种情况(见下文):
//var typeCatalog=新的typeCatalog(typeof(SessionModel));
//var compositionContainer=新的compositionContainer(类型目录);
compositionContainer.ComposeExportedValue(sessionModel);
var someService=compositionContainer.GetExportedValue();
someService.DoSomething();
}
}
公共类会话模型
{
私有int AValue{get;set;}
[出口]
公共服务SomeService{get;private set;}
公共会话模型(int aValue)
{
AValue=AValue;
//当然,在现实中还有很多事情要做:
SomeService=新的SomeService();
}
}
公共接口服务
{
无效剂量();
}
公共类SomeService:ISomeService
{
公共无效剂量测定法()
{
控制台。WriteLine(“称为DoSomething”);
}
}
}
问题 <>我希望MEF考虑服务定位器在编写其他部件时导出的部分(即<代码> SooService < /代码>),但不幸的是这不起作用。 第一例 当我尝试获取
ISomeService
的导出值时,有一个
System.ComponentModel.Composition.ImportCardinalistMatchException
告诉我没有具有此合同名称和所需类型标识的导出(
ConsoleApplication1.ISomeService

第二种情况 如果使用
TypeCatalog
创建
CompositionContainer
,则例外情况略有不同。这是一个
系统.ComponentModel.Composition.CompositionException
告诉我MEF找不到创建
控制台应用程序1.SessionModel
(这是正确的,也是我自己这么做的原因)

补充资料
mefx
对这两种情况都说明:

[Part] ConsoleApplication1.SessionModel from: DirectoryCatalog (Path=".")
  [Export] ConsoleApplication1.SessionModel.SomeService (ContractName="ConsoleApplication1.ISomeService")

[Part] ConsoleApplication1.SessionModel from: AssemblyCatalog (Assembly="ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
  [Export] ConsoleApplication1.SessionModel.SomeService (ContractName="ConsoleApplication1.ISomeService")

我该怎么办?这在MEF中是可能的,还是我必须使用Unity或StructureMap,或者其他什么?这可以通过实现一个
导出提供者来实现吗?

问题是SomeService是一个实例属性。您的系统中可能有几个SessionModel对象,而MEF无法知道哪个SessionModel正在返回应该与导入匹配的ISomeService实例

相反,只需将SessionModel设置为静态类,将SomeService设置为静态属性。或者,将SessionModel设置为单例。SomeService属性仍然是静态的,但会从SessionModel的唯一实例导出服务。

使用System;
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.ReflectionModel;
using System.Reflection;
using System.Linq;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {

            var catalogs = new AggregateCatalog();
            var catalog = new System.ComponentModel.Composition.Hosting.AssemblyCatalog(Assembly.GetExecutingAssembly());
            catalogs.Catalogs.Add(catalog);
            var sessionModel = new SessionModel(3);
            var container = new CompositionContainer(catalog); 
            ISomeService someService = container.GetExportedValueOrDefault<ISomeService>(sessionModel.cname);
            if (someService != null)
            {
                someService.DoSomething();
            }
        }
    }

    public class SessionModel
    {
        private int AValue { get; set; }

        //[Import("One",typeof(ISomeService))]
        //public ISomeService SomeService { get; private set; }

        public SessionModel(int aValue)
        {
            AValue = aValue;
            // of course, there is much more to do here in reality:
        }

        public string cname { get { return "One"; } }
    }

    public class SessionModel1
    {
        private int AValue { get; set; }

        //[Import("Two",typeof(ISomeService))]
        //public ISomeService SomeService { get; private set; }

        public SessionModel1(int aValue)
        {
            AValue = aValue;
        }
        public string cname { get { return "Two"; } }

    }

    public interface ISomeService
    {
        void DoSomething();
    }

    [Export("One",typeof(ISomeService))]
    public class SomeService : ISomeService
    {
        public SomeService()
        {
            Console.WriteLine("Some Service Called");
        }
        public void DoSomething()
        {
            Console.WriteLine("DoSomething called");
            Console.ReadKey();
        }
    }

    [Export("Two",typeof(ISomeService))]
    public class SomeService1 : ISomeService
    {
         public SomeService1()
        {
            Console.WriteLine("Some Service1 Called");
        }
        public void DoSomething()
        {
            Console.WriteLine("DoSomething called 1");
            Console.ReadKey();
        }
    }
}
使用System.ComponentModel.Composition; 使用System.ComponentModel.Composition.Hosting; 使用System.ComponentModel.Composition.ReflectionModel; 运用系统反思; 使用System.Linq; 命名空间控制台应用程序1 { 内部课程计划 { 私有静态void Main(字符串[]args) { var catalogs=new AggregateCatalog(); var catalog=new System.ComponentModel.Composition.Hosting.AssemblyCatalog(Assembly.getExecutionGassembly()); 目录.目录.添加(目录); var sessionModel=新sessionModel(3); var容器=新的合成容器(目录); ISomeService someService=container.GetExportedValueOrDefault(sessionModel.cname); if(someService!=null) { someService.DoSomething(); } } } 公共类会话模型 { 私有int AValue{get;set;} //[导入(“一”,类型(服务))] //公共服务SomeService{get;private set;} 公共会话模型(int aValue) { AValue=AValue; //当然,在现实中还有很多事情要做: } 公共字符串cname{get{返回“一”;} } 公共类会话模型1 { 私有int AValue{get;set;} //[导入(“两个”,类型(服务))] //公共服务SomeService{get;private set;} 公共会话模型1(int aValue) { AValue=AValue; } 公共字符串cname{get{return“Two”;} } 公共接口服务 { 无效剂量(); } [导出(“一”,类型(服务))] 公共类SomeService:ISomeService { 公共服务 { WriteLine(“一些被调用的服务”); } 公共无效剂量测定法() { 控制台。WriteLine(“称为DoSomething”); Console.ReadKey(); } } [导出(“两个”,类型(服务))] 公共类SomeService1:ISomeService { 公共服务1() { Console.WriteLine(“调用的某些服务”); } 公共无效剂量测定法() { 控制台。WriteLine(“DoSomething称为1”); Console.ReadKey(); } } }
第一种情况:通过将
会话模型
传递到
ComposeExportedValue
可以添加类型为
会话模型
的一部分,而不是的一部分
compositionContainer.ComposeExportedValue(sessionModel.SomeService);
public class SessionModelExportProvider : ExportProvider
{
    private List<Export> Exports { get; set; }

    public SessionModelExportProvider(SessionModel sessionModel)
    {
        // get all the properties of the session model having an Export attribute
        var typeOfSessionModel = typeof (SessionModel);
        PropertyInfo[] properties = typeOfSessionModel.GetProperties();
        var propertiesHavingAnExportAttribute =
            from p in properties
            let exportAttributes = p.GetCustomAttributes(typeof (ExportAttribute), false)
            where exportAttributes.Length > 0
            select new
                       {
                           PropertyInfo = p,
                           ExportAttributes = exportAttributes
                       };

        // creating Export objects for each export
        var exports = new List<Export>();
        foreach (var propertyHavingAnExportAttribute in propertiesHavingAnExportAttribute)
        {
            var propertyInfo = propertyHavingAnExportAttribute.PropertyInfo;
            foreach (ExportAttribute exportAttribute in propertyHavingAnExportAttribute.ExportAttributes)
            {
                string contractName = exportAttribute.ContractName;
                if (string.IsNullOrEmpty(contractName))
                {
                    Type contractType = exportAttribute.ContractType ?? propertyInfo.PropertyType;
                    contractName = contractType.FullName;
                }

                var metadata = new Dictionary<string, object>
                                   {
                                       {CompositionConstants.ExportTypeIdentityMetadataName, contractName},
                                       {CompositionConstants.PartCreationPolicyMetadataName, CreationPolicy.Shared}
                                   };
                var exportDefinition = new ExportDefinition(contractName, metadata);
                var export = new SessionModelExport(sessionModel, propertyInfo, exportDefinition);
                exports.Add(export);
            }
        }

        Exports = exports;
    }

    protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition,
                                                          AtomicComposition atomicComposition)
    {
        return Exports.Where(e => definition.IsConstraintSatisfiedBy(e.Definition));
    }
}

public class SessionModelExport : Export
{
    private readonly SessionModel sessionModel;
    private readonly PropertyInfo propertyInfo;
    private readonly ExportDefinition definition;

    public SessionModelExport(SessionModel sessionModel, PropertyInfo propertyInfo, ExportDefinition definition)
    {
        this.sessionModel = sessionModel;
        this.propertyInfo = propertyInfo;
        this.definition = definition;
    }

    public override ExportDefinition Definition
    {
        get { return definition; }
    }

    protected override object GetExportedValueCore()
    {
        var value = propertyInfo.GetValue(sessionModel, null);
        return value;
    }
}