2010-10-28 2 views
0

Так что я некоторое время работал над созданием решения, которое создает определенные компоненты, используя ничего, кроме Castle DynamicProxy (версия 2.2) и перехватчик. Все выглядит великолепно, за исключением того, что в конце всего этого я понял, что мне нужно зарегистрировать эти компоненты с контейнером Windsor. Возможно ли это, или моя работа была напрасной?Регистрация компонентов с замком, которые динамически создаются DynamicProxy

Я соберу 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> 

Второй конфигурации (я не знаю, что поставить в атрибуте типа и он не работает без него):

<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 с использованием динамического прокси, создавая прокси без целей. I.e., я использую метод ProxyGenerator.CreateInterfaceProxyWithoutTarget, поэтому нет базового класса.

Итак, есть ли какая-либо надежда на регистрацию компонентов по второй конфигурации?

EDIT: К сожалению, использование свободного API конфигурации в настоящий момент не является вариантом. Поэтому, чтобы сузить мой вопрос, можно ли достичь этого, используя конфигурацию XML?

+0

Вы пробовали с помощью свободно (на основе кода) механизм регистрации для сфабрикованного сценария? Я хотел бы сделать это, используя расширение «UsingFactoryMethod» для вызова вашего кода, который создает реализатор DynamicProxy интерфейса ILoader. При наличии свободного API регистрации вам не нужно указывать конкретный тип при регистрации заводской службы. –

ответ

2

Я считаю, что это возможно через Fluent Registration API и механизм «UsingFactoryMethod». Я попытался воспроизвести ваш сфабрикованный сценарий в приведенном ниже тестовом примере.

UPDATE

Это в самом деле можно с конфигурацией XML, а также. Хитрость заключается только в том, чтобы перечислить сам интерфейс как «тип» в конфигурации (или, что то же самое, указать только «тип», поскольку «служба» будет установлена ​​на «тип», если она явно не предусмотрена). Я обновил тестовый пример ниже, чтобы включить тест TestXml, который использует xml-конфигурацию для достижения желаемого результата. Тест «TestFluent» использует свободный API регистрации для его достижения. FYI, я использую 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> 
+0

Спасибо, это полезная информация, но, к сожалению, использование свободной регистрации для меня сейчас не вариант. – joniba

+0

У меня был другой взгляд и я понял, как это сделать через xml - см. Мой обновленный ответ. –

+0

Спасибо, сэр, это отлично выглядит. Так неожиданно просто! Я проверю его, когда вернусь к работе в воскресенье. – joniba

Смежные вопросы