0

因此,我一直在努力构建一个解决方案,该解决方案只使用 Castle DynamicProxy(2.2 版)和拦截器来创建某些组件。一切看起来都很棒,除了在这一切结束时我意识到我需要将这些组件注册到 windsor 容器。这是可能的还是我的工作是徒劳的?

我将制作 2 个城堡配置来解释我的问题。第一个有效,而第二个无效。

第一个配置(这已经工作了一段时间):

<castle>
  <facilities>
    <facility
        id="factory.support"
        type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />
  </facilities>

  <components>
    <component
        id="Factory"
        service="Foo.IFactory, Foo"
        type="Foo.Local.LocalFactory, Foo.Local" />
    <component
        id="Loader"
        service="Foo.Contracts.ILoader, Foo.Contracts"
        type="Foo.Local.Loader, Foo.Local"
        factoryId="Factory" factoryCreate="GetLoader" />
  </components>
</castle>

第二个配置(我不知道在 type 属性中放什么,没有它就无法工作):

<castle>
  <facilities>
    <facility
        id="factory.support"
        type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />
  </facilities>

  <components>
    <component
        id="Factory"
        service="Foo.IFactory, Foo"
        type="Foo.Remote.RemoteFactory, Foo.Remote" />
    <component
        id="Loader"
        service="Foo.Contracts.ILoader, Foo.Contracts"
        type="I DUNNO, WHAT'S THE TYPE?"
        factoryId="Factory" factoryCreate="GetLoader" />
  </components>
</castle>

所以我制造的配置注册了工厂设施,然后我注册了工厂,然后注册了我的“ILoader”组件。“LocalFactory”为 ILoader 组件创建一个实际类型,而“RemoteFactory”使用动态代理创建 ILoader 组件,创建没有目标的代理。即我使用的是ProxyGenerator.CreateInterfaceProxyWithoutTarget方法,所以没有底层类。

那么,根据第二个配置注册组件有什么希望吗?

编辑:不幸的是,目前不能选择使用流畅的配置 API。所以为了缩小我的问题,是否可以使用 XML 配置来实现这一点?

4

1 回答 1

2

我相信这可以通过Fluent Registration API和“UsingFactoryMethod”机制实现。我试图在下面的测试用例中复制你虚构的场景。

更新

这实际上也可以通过 XML 配置实现。诀窍只是将接口本身列为配置中的“类型”(或者,等效地,仅指定“类型”,因为如果未明确提供“服务”将被设置为“类型”)。我已经更新了下面的测试用例以包含一个“TestXml”测试,该测试使用 xml 配置来实现您想要的结果。"TestFluent" 测试使用 fluent 注册 API 来实现。仅供参考,我在这里使用的是 Castle Windsor 2.0,因为我猜这就是您正在使用的。

using Castle.DynamicProxy;
using Castle.Facilities.FactorySupport;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NUnit.Framework;

namespace CastleTests
{
    public interface ILoader
    {
        void Load();
    }

    public interface ILoaderFactory
    {
        ILoader GetLoader();
    }

    public class LoaderFactory : ILoaderFactory
    {
        public ILoader GetLoader()
        {
            return GetLoaderStatic();
        }

        public static ILoader GetLoaderStatic()
        {
            return (ILoader) new ProxyGenerator().CreateInterfaceProxyWithoutTarget(typeof (ILoader));
        }
    }

    [TestFixture]
    public class DynamicFactoryTests
    {
        [Test]
        public void TestFluent()
        {
            using (var container = new WindsorContainer())
            {
                container.AddFacility<FactorySupportFacility>();
                container.Register(
                    Component.For<ILoader>().UsingFactoryMethod(() => LoaderFactory.GetLoaderStatic())
                    );
                var loader = container.Resolve<ILoader>();
                Assert.That(loader.GetType().FullName, Is.EqualTo("Castle.Proxies.ILoaderProxy"));
            }
        }

        [Test]
        public void TestXml()
        {
            using (var container = new WindsorContainer("factory.xml"))
            {
                var loader = container.Resolve<ILoader>();
                Assert.That(loader.GetType().FullName, Is.EqualTo("Castle.Proxies.ILoaderProxy"));
            }
        }
    }
}

“factory.xml”的内容因此是:

<castle>
  <facilities>
    <facility
        id="factory.support"
        type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />
  </facilities>
  <components>
    <component
        id="foo"
        service="CastleTests.ILoaderFactory, CastleTests"
        type="CastleTests.LoaderFactory, CastleTests" />
    <component
        id="bar"
        type="CastleTests.ILoader, CastleTests"
        factoryId="foo" factoryCreate="GetLoader" />
  </components>
</castle>
于 2010-10-28T16:56:36.920 回答