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

本文关键字:我的 发现 MEF 为什么 | 更新日期: 2023-09-27 17:54:04

我想使用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);
        }
    }
}

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

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

您试图导出一个打开的泛型类型,但您的对象实际上并没有在该导出上关闭。导出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);
    }
}