2008-09-17 22 views
11

Nói rằng tôi có lớp sauCastle Windsor: Cách chỉ định tham số hàm tạo từ mã?

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

Tôi có thể đăng ký một thể hiện của nó với lâu đài windsor qua xml như sau

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

Làm thế nào tôi sẽ đi về làm chính xác những điều tương tự, nhưng trong mã? (Thông báo, thông số hàm tạo)

Trả lời

15

Edit: Được sử dụng các câu trả lời dưới đây mã với giao diện thạo :)

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

Giải pháp này có hoạt động nếu tham số là một loại phức tạp, chẳng hạn như một IMyComponent khác không? – flipdoubt

+0

Nếu phụ thuộc trong thùng chứa, nó sẽ tự động được giải quyết –

+0

Tôi muốn sử dụng giao diện thông thạo, tuy nhiên tải xuống nguồn lâu đài, nant (mà tôi chưa bao giờ sử dụng trước đó) và tìm ra tất cả chỉ một chút là –

0

Bạn cần chuyển IDictionary khi bạn yêu cầu vùng chứa cho cá thể đó.

Bạn muốn sử dụng quá tải này Resolve của IWindsorContainer:

T Resolve<T>(IDictionary arguments) 

hoặc không chung một:

object Resolve(Type service, IDictionary arguments) 

Vì vậy, ví dụ: (giả sử container là một IWindsorContainer)

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

Lưu ý rằng các giá trị khóa trong từ điển phân biệt chữ hoa chữ thường.

+0

Xin lỗi Gareth, nhưng điều này không phải là điều tương tự như XML Tôi đăng. Ở đây, tham số cần được trình phân giải biết đến trong khi câu hỏi XML cung cấp một giá trị mặc định. –

+0

+1 để giải quyết một vấn đề khác - khởi tạo một đối tượng có tham số được truyền vào thời gian chạy. –

-1

Bạn có thể sử dụng phương pháp AddComponentWithProperties của giao diện IWindsorContainer đăng ký một dịch vụ với tính chất mở rộng.

Dưới đây là mẫu 'đang hoạt động' thực hiện việc này với Thử nghiệm đơn vị 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

có xung quanh để cố gắng này, nó không hoạt động: Không thể giải quyết phụ thuộc không tùy chọn cho 'bê tông' (WindsorSample.MyComponent). Tham số 'start_at' type 'System.Int32' –

1

Bạn đã cân nhắc sử dụng Binsor để định cấu hình vùng chứa của mình chưa? Thay vì XML dài dòng và vụng về, bạn có thể cấu hình Windsor bằng cách sử dụng DSL dựa trên Boo. Dưới đây là cấu hình của bạn trông như thế nào:

component IMyComponent, MyComponent: 
    start_at = 1 

Lợi thế là bạn có tệp cấu hình có thể chia sẻ nhưng tránh các vấn đề với XML. Ngoài ra, bạn không phải biên dịch lại để thay đổi cấu hình của bạn như bạn sẽ làm nếu bạn cấu hình container trong mã.

Ngoài ra còn có rất nhiều các phương pháp helper cho phép zero cấu hình ma sát:

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 

Bạn có thể bắt đầu với nó here.

+0

Khi tôi nhận được hơn 3 giây cho bản thân mình, tôi dự định sẽ xem xét nó. Nó cũng quan trọng đối với tôi rằng đây là một cái gì đó tôi có thể thay đổi mà không cần biên dịch lại kể từ khi tôi có kế hoạch để bật/tắt đánh chặn để gỡ lỗi ứng dụng trong lĩnh vực –

2

Hãy thử điều này

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

bạn có thể giải thích thêm một chút? –

+0

Đây là một nỗ lực trung thực tại một câu trả lời và do đó không được gắn cờ không phải là câu trả lời. Nếu bạn không thích câu trả lời, bạn nên downvote nó, không đánh dấu nó. – ArtOfWarfare

Các vấn đề liên quan