为什么MEF没有发现我的通用出口?

时间:2015-06-08 10:35:41

标签: c# generics mef

我想使用MEF使用队列插件。我已尝试过以下内容,但以下字段queuePlugins和alternativeApproach,使用Import属性进行装饰(在以下示例中)为空 任何的想法? 谢谢, 原子

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Reflection;

namespace MefIsHell
{
    class Program
    {
        static void Main(string[] args)
        {
            QueueFactory<string> qf = new QueueFactory<string>();
            var queue = qf.GetQueue(QueueProviderType.InProcess);
        }
    }

    public class QueueFactory<T> : IPartImportsSatisfiedNotification where T : class
    {
        [ImportMany]
        private IEnumerable<Lazy<IQueueProviderPlugin<T>, IQueuePluginMetadata>> queuePlugins = null;

        [ImportMany(typeof(IQueueProviderPlugin<>))]
        private IEnumerable<IQueueProviderPlugin<T>> alternativeApproach;

        public QueueFactory ()
        {
            ComposeMEF();
        }
        private void ComposeMEF()
        {
            var catalog = new DirectoryCatalog(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            CompositionContainer container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }

        public void OnImportsSatisfied()
        {
            if (!queuePlugins.Any())
            {
                Console.WriteLine("queuePlugins is empty");
            }
            if (!alternativeApproach.Any())
            {
                Console.WriteLine("alternativeApproach is empty");
            }
        }

        public IQueueProviderPlugin<T> GetQueue(QueueProviderType QueueType)
        {
            var plugins = from lazyPlugin in queuePlugins
                          let metadata = lazyPlugin.Metadata
                          where metadata.QueueType == QueueType
                          select lazyPlugin.Value;

            if (plugins.Count() == 0)
            {
                throw new ApplicationException("No plugins!!!");
            }

            return plugins.First();
        }
    }
    public interface IQueueProviderPlugin<T>
    {
        void Enqueue(T item);
        T Dequeue();
    }

    public enum QueueProviderType
    {
        InProcess,
        RabbitMQ
    }

    public interface IQueuePluginMetadata
    {
        QueueProviderType QueueType { get; }
    }

    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class QueueTypeAttribute : ExportAttribute, IQueuePluginMetadata
    {
        public QueueTypeAttribute(QueueProviderType QueueType)
            : base(typeof(IQueueProviderPlugin<>))
        {
            this.QueueType = QueueType;
        }

        public QueueProviderType QueueType { get; private set; }
    }

    [QueueTypeAttribute(QueueProviderType.InProcess)] // : ExportAttribute !!!
    [Export(typeof(IQueueProviderPlugin<>))]          // duplicate export
    public class InProcessQueuePlugin : IQueueProviderPlugin<string>
    {
        private Queue<string> _queue = new Queue<string>();

        public string Dequeue()
        {
            return _queue.Dequeue();
        }

        public void Enqueue(string item)
        {
            _queue.Enqueue(item);
        }
    }
}

2 个答案:

答案 0 :(得分:0)

查看可能的解决方案 https://social.msdn.microsoft.com/Forums/vstudio/en-US/02a2a0b9-0c3e-4ba1-a525-ffa3a140bae9/why-mef-does-not-discover-my-exports?forum=csharpgeneral 如果您有更好的MEF Vs解决方案,请更新。泛型问题。 问候, 原子

答案 1 :(得分:0)

当您的对象实际上未通过该导出关闭时,您正在尝试导出一个打开的泛型类型。要导出IQueueProviderPlugin<string>,请使用[Export(typeof(IQueueProviderPlugin<string>))]而不是[Export(typeof(IQueueProviderPlugin<>))]

如果您想导出IQueueProviderPlugin<>,则必须将导出设置为开放(未封闭)通用类型:

[QueueTypeAttribute(QueueProviderType.InProcess)] // exports IQueueProviderPlugin<>
public class InProcessQueuePlugin<T> : IQueueProviderPlugin<T>
{
    readonly Queue<T> _queue = new Queue<T>();

    public T Dequeue() => _queue.Dequeue();

    public void Enqueue(T item)
    {
        _queue.Enqueue(item);
    }
}