C# MEF DirectoryCatalog在加载时不会覆盖项目引用

C# MEF DirectoryCatalog在加载时不会覆盖项目引用,c#,mef,altova,C#,Mef,Altova,我有一个如下的界面: namespace Contract { [InheritedExport(typeof(ITransform))] public interface ITransform { string process(string name); } } 现在,我有两门课: using Contract; namespace ProjectA { public class ProjectA:ITransform {

我有一个如下的界面:

namespace Contract
{
    [InheritedExport(typeof(ITransform))]
    public interface ITransform
    {
       string process(string name);
    }
}
现在,我有两门课:

using Contract;
namespace ProjectA
{
    public class ProjectA:ITransform
    {

        public string process(string name)
        {
            ProjectXYZ.ProjectXYZ obj = new ProjectXYZ.ProjectXYZ();
            return obj.process("Project A calling");
        }
    }
}

我有另一个项目ProjectXYZauto,由第三方工具Altova Mapforce 2012 SP1生成

对于ProjectA,来自altova mapforce 2012的自定义自动生成代码:

namespace ProjectXYZ
{
    public class ProjectXYZ
    {
        public string process(string name)
        {
            name = "This is for Project A :: "+name;
            return name;
        }
    }
}
namespace ProjectXYZ
{
    public class ProjectXYZ
    {
        public string process(string name)
        {
            string n = "This is for Project B ::"+Result();
            return n;
        }
        public string Result()
        { 
            int op1 = 1;
            int op2 = op1+3;
            return op2.ToString();
        }
    }
}
对于ProjectB,来自altova mapforce 2012的自定义自动生成代码:

namespace ProjectXYZ
{
    public class ProjectXYZ
    {
        public string process(string name)
        {
            name = "This is for Project A :: "+name;
            return name;
        }
    }
}
namespace ProjectXYZ
{
    public class ProjectXYZ
    {
        public string process(string name)
        {
            string n = "This is for Project B ::"+Result();
            return n;
        }
        public string Result()
        { 
            int op1 = 1;
            int op2 = op1+3;
            return op2.ToString();
        }
    }
}
第三方自动生成的代码不会导出,但其二进制文件我用作ProjectA.Transform和ProjectB.Transform的参考,因此我使用[DirectoryCatalog]在MEF的CompositionContainer中加载ProjectA.Transform和ProjectB.Transform的所有二进制文件。每个项目都经过编译,它们的二进制生成输出位置作为DirectoryCatalog的输入

为进一步的组成

using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition;
namespace AppConsole
{       
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Run();
        }
        public void Run() {

            List<string> extensionPath = new List<string>();
            //Change the extension Path
            extensionPath.Add(@"E:\MEF\MEFForProjectA\ProjectA\bin\Debug");
            extensionPath.Add(@"E:\MEF\MEFForProjectB\ProjectB\bin\Debug");
            foreach (var extension in extensionPath)
            {
                ITransform transform = GetExtension(extension);
                Console.WriteLine("Extension Loaded :{0}", transform.process(extension));

            }
            Console.ReadLine();
        }
        private ITransform GetExtension(string extensionPath)
        {            
            IEnumerable<ITransform> extensions = null;          
            try
            {                
                AggregateCatalog catalog = new AggregateCatalog();
                catalog.Catalogs.Add(new DirectoryCatalog(extensionPath));      
                CompositionContainer container = new CompositionContainer(catalog);
                container.ComposeParts(catalog);
                extensions = container.GetExportedValues<ITransform>();
                return extensions.FirstOrDefault();
            }
            catch (Exception ex) { Console.WriteLine(ex.Message); }
            return extensions.FirstOrDefault(); 
        }        
    }
}

我认为这将是元数据的一个例子。MEF无法确定要使用哪个ITransform实例,因为您始终使用GetExportedValues.FirstOrDefault。如果您向部件提供元数据,例如:

首先,定义元数据接口:

public interface ITransformMetadata
{
    string Name { get; }
}
和自定义导出属性:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute]
public class ExportTransformAttribute : ExportAttribute, ITransformMetadata
{  
    public ExportTransformAttribute(string name)
        : base(typeof(ITransform))
    {
        Name = name;
    }

    public string Name { get; set; }
}
然后,您可以开始使用其他元数据丰富导出内容,您可以稍后查询这些元数据,例如:

[ExportTransform("ClassB")]
public class ClassBTransform : ITransform { }
还有一个问题:

var part = container.GetExports<ITransform, ITransformMetadata>()
    .Where(e => e.Metadata.Name.Equals("value"))
    .FirstOrDefault();
return part.Value;
编辑:导出类型时,会提供一段特殊的元数据,称为ExportTypeIdentity,它使用导出类型的名称空间+名称


在代码中,两个程序集上有两个具有相同名称空间和名称的部件。ProjectXYZ.ProjectXYZ。将其与您的第一个或默认值相结合可能是您的问题。

这不是MEF问题。问题在于.NET的加载模型。或者更好地使用.net加载对象的方式

当MEF加载时,它返回正确的对象。但在加载projectB时查找类ProjectXYZ时,已经有一个ProjectXYZ dll加载了projectB所引用的正确程序集名称。并且projectB实际引用的dll加载程序未加载

您可以自己尝试,只需将添加文件夹的顺序更改为

扩展路径。Add@E:\MEF\MEFForProjectB\ProjectB\bin\Debug; 扩展路径。Add@E:\MEF\MEFForProjectA\ProjectA\bin\Debug

然后你得到

已加载扩展:这是针对项目B::4的 已加载扩展:这是针对项目B::4的

您的问题的解决方案是重命名程序集。当所有ProjectXYZ程序集都有自己的文件名时,您将得到预期的结果

问候,,
Piet

可能重复的Yes Matthew都是相同的。这是我公司同事添加的。这是个关键问题,我完全被封锁了。如果您有任何想法,请通知我。我也在Codeproject.com和mef.codeplex.com上提出了相同的问题。我尝试在AssemblyCatalog和Typecatalog上工作。但每次它都是在ProjectB的地方引用ProjectA。提前谢谢。这不管用。首先,我在MEF容器内存ProjectXYZProjectA中为ProjectA加载projectXYZ。第二次,我用ProjectXYZProjectB加载ProjectB。但支持ProjectXYZ的ProjectA已经在MEF容器内存中,并且具有相同的程序集名称。MEF不会加载ProjectXYZProjectB,因为ProjectXYZProjectA已在MEF内存中。所以当我调用ProjectXYZ作为ProjectB的参考,但是在MEF内存中ProjectXYZProjectA代替ProjectB,所以它不工作。如果您需要密码,请通知我。我会用你的电子邮箱发给你。你真的需要用一个实际的例子来解释。嗨,马修,按照你的要求。在这里我上传了整个解决方案。如果您还需要什么,请通知我。我会把全部源代码寄给你。亲爱的皮特,我知道这都是问题所在。我试着找出解决问题的办法,因为当我通知客户这个问题时,我需要尽一切努力来解决这个问题。我知道这是.Net加载问题。但是当解决方案的所有门关闭时,我会改变加载逻辑吗?谢谢你花时间解决我的问题。如果您找到任何解决方案,请提前向您表示感谢。