Импорт MEF из ядра замка в Silverlight - PullRequest
2 голосов
/ 29 июля 2011

В настоящее время я использую MEF в своем проекте, однако устаревший компонент использует Castle для экспорта всех своих компонентов.

Я хотел бы иметь возможность импортировать из этого ядра при создании новых объектов, в дополнениеполучить экспорт из Xap.

Возможно ли это?Можете ли вы показать мне пример кода?

Ответы [ 2 ]

2 голосов
/ 29 июля 2011

MEF был спроектирован так, чтобы быть максимально гибким, и одна из его секретно скрытых, но действительно приятных функций - это возможность определять новые ExportProvider экземпляры, которые позволяют подключать дополнительные компоненты. Я говорил об этом ранее, используя проект Common Service Locator в ASP.NET MVC с MEF Project (см. Часть 3 здесь ).

CSL - это хороший гибкий подход, поскольку существует множество конкретных реализаций CSL для многих из существующих контейнеров IoC, таких как Castle, Autofac, Ninject, Unity и т. Д.

Еще один хороший пример можно найти здесь , который демонстрирует несколько иной, но принципиально похожий подход.

1 голос
/ 01 августа 2011

Как правильно сказал Мэтью, способ сделать это - использовать ExportProvider

Другой пример - здесь (демонстрирует экспорт из Xaml). Ниже, в конце концов, я решил проблему.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Linq;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.Windsor;

namespace MEFCastleBridge
{
    public class CastleExportProvider : ExportProvider
    {
        WindsorContainer _container;
        private readonly Dictionary<ExportDefinition, List<Export>> _exports =
            new Dictionary<ExportDefinition, List<Export>>();
        private readonly object _sync = new object();

        public CastleExportProvider(WindsorContainer container)
        {
            _container = container;
            var handlers = _container.Kernel.GetAssignableHandlers(typeof(object));
            foreach (var handler in handlers)
            {
                RegisterCastleComponent(handler);
            }
            _container.Kernel.ComponentRegistered += ComponentRegistered;
        }

        protected override IEnumerable<Export> GetExportsCore(
            ImportDefinition definition, AtomicComposition atomicComposition)
        {
            var contractDefinition = definition as ContractBasedImportDefinition;
            var retVal = Enumerable.Empty<Export>();
            if (contractDefinition != null)
            {
                string contractName = contractDefinition.ContractName;
                if (!string.IsNullOrEmpty(contractName))
                {
                    var exports =
                       from e in _exports
                       where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                       select e.Value;

                    if (exports.Count() > 0)
                    {
                        retVal = exports.First();
                    }
                }
            }

            return retVal;
        }

        void RegisterCastleComponent(IHandler handler)
        {
            var type = handler.Service;
            var contractName = type.ToString();
            lock (_sync)
            {
                var found = from e in _exports
                            where string.Compare(e.Key.ContractName, 
                                contractName, StringComparison.OrdinalIgnoreCase) == 0
                            select e;

                if (found.Count() == 0)
                {
                    var metadata = new Dictionary<string, object>();
                    var definition = new ExportDefinition(contractName, metadata);
                    _exports.Add(definition, new List<Export>());
                }

                var wrapper = new Export(contractName, () => _container.Resolve(type));
                found.First().Value.Add(wrapper);
            }
        }

        void ComponentRegistered(string key, IHandler handler)
        {
            RegisterCastleComponent(handler);
        }
    }

    public interface IMyComponent
    {
        string TheString { get; }
    }

    public class RegisteredComponent : IMyComponent
    {
        public string TheString { get { return "RegisteredComponent"; } }
    }

    [Export(typeof(IMyComponent))]
    public class ExportedComponent : IMyComponent
    {
        public string TheString { get { return "ExportedComponent"; } }
    }

    public class ExportExample
    {
        // Will contain an instance of RegisteredComponent and ExportedComponent
        [ImportMany]
        public List<IMyComponent> Components { get; set; }

        public ExportExample()
        {
            // Create a Windsor container and add a type.
            var container = new WindsorContainer();
            container.Register(Component.For<IMyComponent>().ImplementedBy<MyComponent>().LifeStyle.Singleton);

            // Add the Export Provider, in addition to the DeploymentCatalog
            var compContainer = new CompositionContainer(new DeploymentCatalog(), new CastleExportProvider(container));
            // Should only be called once, before any attempt to SatisfyImports.
            CompositionHost.Initialize(compContainer);
            CompositionInitializer.SatisfyImports(this);

            Test = string.Join(", ", Components.Select(c => c.DoSomething));
        }

        public string Test { get; set; }
    }
}
...