0

そのため、Castle DynamicProxy (バージョン 2.2) とインターセプターだけを使用して特定のコンポーネントを作成するソリューションを構築するために、しばらく懸命に取り組んできました。これらすべてが終わったときに、これらのコンポーネントをウィンザー コンテナーに登録する必要があることに気付きました。これは可能ですか、それとも私の仕事は無駄になりましたか?

私の問題を説明するために、2 つの城の構成を作成します。最初のものは機能しますが、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>

2 番目の構成 (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 メソッドを使用するため、基になるクラスはありません。

では、2 番目の構成に従ってコンポーネントを登録する希望はありますか?

編集: 残念ながら、流暢な構成 API を使用することは、現時点ではオプションではありません。私の質問を絞り込むために、XML構成を使用してこれを達成することは可能ですか?

4

1 に答える 1

2

これは、Fluent Registration APIと「UsingFactoryMethod」メカニズムによって可能になると思います。以下のテストケースで、作成したシナリオを再現しようとしました。

アップデート

実際、これは XML 構成でも可能です。トリックは、構成で「タイプ」としてインターフェイス自体をリストすることです(または、明示的に指定されていない場合は「サービス」が「タイプ」に設定されるため、同等に「タイプ」のみを指定します)。以下のテスト ケースを更新して、xml 構成を使用して目的の結果を達成する「TestXml」テストを含めました。「TestFluent」テストは、流暢な登録 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 に答える