从 Silverlight 中的 Castle 内核导入 MEF

发布于 2024-11-27 03:53:37 字数 118 浏览 1 评论 0原文

我目前在我的项目中使用 MEF,但是,遗留组件使用 Castle 导出其所有组件。

除了从 Xap 获取导出之外,我希望在创建新对象时能够从该内核导入。

这可能吗?你能给我看一些示例代码吗?

I'm currently using MEF in my project, however, a legacy component uses Castle to export all its components.

I would like to be able to Import from this kernel when creating new objects, in addition to getting the exports from the Xap.

Is this possible? Can you show me some example code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风流物 2024-12-04 03:53:37

MEF 被设计得尽可能灵活,其秘密隐藏但真正出色的功能之一是能够定义新的 ExportProvider 实例,允许您插入其他组件。我之前已经通过在带有 MEF 项目的 ASP.NET MVC 中利用 Common Service Locator 项目讨论过这一点(请参阅第 3 部分 此处)。

CSL 是一种非常灵活的方法,因为许多现有的 IoC 容器都有许多特定的 CSL 实现,例如 Castle、Autofac、Ninject、Unity 等。

另一个很好的示例可以在 此处,它演示了一种略有不同但基本相似的方法。

MEF was designed to be as flexible as possible, and one of its secretly hidden but real nice features, is the ability to define new ExportProvider instances, that allow you to plug in additional components. I've talked about this previously by utilising the Common Service Locator project in an ASP.NET MVC with MEF Project (see part 3 here).

The CSL is a nice flexible approach, as there are many specific CSL implementations for many of the existing IoC containers, such as Castle, Autofac, Ninject, Unity etc.

Another good example can be found here, which demonstrates a slightly different, but fundamentally similar approach.

帅气尐潴 2024-12-04 03:53:37

正如马修正确所说,做到这一点的方法是使用 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; }
    }
}

As Matthew correctly said, the way to do this is using an ExportProvider

Another example is here (it demonstrates exports from Xaml).
Below is what I did in the end to solve the problem.

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; }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文