2008-09-17 21 views
11

Say mam następujące klasyCastle Windsor: Jak określić parametr konstruktora z kodu?

MyComponent : IMyComponent { 
    public MyComponent(int start_at) {...} 
} 

mogę zarejestrować wystąpienie go z zamku Windsor poprzez xml następująco

<component id="sample" service="NS.IMyComponent, WindsorSample" type="NS.MyComponent, WindsorSample"> 
    <parameters> 
    <start_at>1</start_at > 
    </parameters> 
</component> 

Jak bym go o to robi dokładnie to samo, ale w kodzie? (Uwaga: parametr konstruktora)

Odpowiedz

15

Edit: Używany odpowiedź poniżej kod z Zaawansowany interfejs :)

namespace WindsorSample 
{ 
    using Castle.MicroKernel.Registration; 
    using Castle.Windsor; 
    using NUnit.Framework; 
    using NUnit.Framework.SyntaxHelpers; 

    public class MyComponent : IMyComponent 
    { 
     public MyComponent(int start_at) 
     { 
      this.Value = start_at; 
     } 

     public int Value { get; private set; } 
    } 

    public interface IMyComponent 
    { 
     int Value { get; } 
    } 

    [TestFixture] 
    public class ConcreteImplFixture 
    { 
     [Test] 
     void ResolvingConcreteImplShouldInitialiseValue() 
     { 
      IWindsorContainer container = new WindsorContainer(); 

      container.Register(
       Component.For<IMyComponent>() 
       .ImplementedBy<MyComponent>() 
       .Parameters(Parameter.ForKey("start_at").Eq("1"))); 

      Assert.That(container.Resolve<IMyComponent>().Value, Is.EqualTo(1)); 
     } 

    } 
} 
+1

Czy to rozwiązanie działa, jeśli parametr jest złożony, na przykład inny komponent IMyComponent? – flipdoubt

+0

Jeśli zależność jest w kontenerze, to zostanie automatycznie rozwiązana. –

+0

Chciałbym użyć płynnego interfejsu, jednak ściąganie źródła zamków, nant (którego nigdy wcześniej nie używałem) i ustalenie tego wszystkiego jest trochę za dużo –

0

Musisz podać IDictionary, gdy poprosisz kontener o wystąpienie.

Można by użyć tego przeciążenia determinacji IWindsorContainer:

T Resolve<T>(IDictionary arguments) 

lub non generic One:

object Resolve(Type service, IDictionary arguments) 

Tak więc, na przykład: (zakładając, że pojemnik jest IWindsorContainer)

IDictionary<string, object> values = new Dictionary<string, object>(); 
values["start_at"] = 1; 
container.Resolve<IMyComponent>(values); 

Należy pamiętać, że w wartościach klucza w słowniku rozróżniana jest wielkość liter.

+0

Sorry Garetha, ale to nie jest to samo, co ja pisał XML. W tym przypadku parametr musi być znany przez resolver, podczas gdy XML ma wartość domyślną. –

+0

+1 za rozwiązanie innego problemu - tworzenie obiektu z parametrem przekazywanym w środowisku wykonawczym. –

-1

Można użyć metody AddComponentWithProperties interfejsu IWindsorContainer zarejestrować usługę z rozszerzonym właściwości.

Poniżej znajduje się "robocza" próbka wykonania tej czynności za pomocą testu jednostki NUnit.

namespace WindsorSample 
{ 
    public class MyComponent : IMyComponent 
    { 
     public MyComponent(int start_at) 
     { 
      this.Value = start_at; 
     } 

     public int Value { get; private set; } 
    } 

    public interface IMyComponent 
    { 
     int Value { get; } 
    } 

    [TestFixture] 
    public class ConcreteImplFixture 
    { 
     [Test] 
     void ResolvingConcreteImplShouldInitialiseValue() 
     { 
      IWindsorContainer container = new WindsorContainer(); 
      IDictionary parameters = new Hashtable {{"start_at", 1}}; 

      container.AddComponentWithProperties("concrete", typeof(IMyComponent), typeof(MyComponent), parameters); 

      IMyComponent resolvedComp = container.Resolve<IMyComponent>(); 

      Assert.That(resolvedComp.Value, Is.EqualTo(1)); 
     } 

    } 
} 
+0

próbowałem tego, to nie działa: Nie można rozwiązać nie-opcjonalnej zależności dla "betonu" (WindsorSample.MyComponent). Parametr "start_at" typ "System.Int32" –

1

Czy rozważałeś użycie Binsora do skonfigurowania swojego kontenera? Zamiast rozwlekłego i niezgrabnego XML-a możesz skonfigurować Windsor używając DSL opartego na Boo. Oto, jak będzie wyglądać twoja konfiguracja:

component IMyComponent, MyComponent: 
    start_at = 1 

Zaletą jest to, że masz konfigurowalny plik, ale unikaj problemów z XML. Nie musisz też rekompilować, aby zmienić konfigurację tak, jakbyś skonfigurował kontener w kodzie.

Istnieje również wiele metod pomocniczych, które umożliwiają konfigurację zerową tarcia:

for type in Assembly.Load("MyApp").GetTypes(): 
    continue unless type.NameSpace == "MyApp.Services" 
    continue if type.IsInterface or type.IsAbstract or type.GetInterfaces().Length == 0 
    component type.GetInterfaces()[0], type 

można zacząć z nim here.

+0

Kiedy otrzymam do siebie więcej niż 3 sekundy, zamierzam rzucić okiem na to. Ważne jest również dla mnie, że to jest coś, co mogę zmienić bez rekompilacji, ponieważ planuję włączyć/wyłączyć przechwytywanie w celu debugowania aplikacji w polu –

2

Spróbuj

int start_at = 1; 
container.Register(Component.For().DependsOn(dependency: Dependency.OnValue(start_at))); 
+1

. Czy możesz wyjaśnić nieco dalej? –

+0

To jest uczciwa próba odpowiedzi, więc nie powinna być oznaczona jako brak odpowiedzi. Jeśli nie podoba ci się odpowiedź, powinieneś ją potwierdzić, a nie oznaczyć. – ArtOfWarfare

Powiązane problemy