2011-07-01 30 views
19

Tôi có các cờ toàn cục bật/tắt các tính năng. Tôi muốn tiêm một số phụ thuộc tùy thuộc vào một số lá cờ. Một số tính năng đòi hỏi các lớp được xây dựng rất nhiều vì vậy tôi muốn tiêm null nếu giá trị của cờ là sai và phụ thuộc thực tế khác. Ninject không cho phép tiêm null. Có sự lựa chọn nào khác không?Ninject. Tùy chọn Tiêm

Cập nhật: đối số hàm tạo có thể được trang trí với thuộc tính OptionalAttribute. Trong trường hợp này null được tiêm nếu không tìm thấy ràng buộc tương ứng. Có vấn đề ở đây: Tôi không thể xác minh xem lớp đích có thể được xây dựng đúng cách hay không. Tôi có một bài kiểm tra cho mỗi phụ thuộc công khai để xác minh xem nó có thể được xây dựng thành công hay không. Trong trường hợp nếu giá trị của cờ là đúng, tôi sẽ không thể tìm thấy lỗi khi phụ thuộc được trang trí với thuộc tính OptionalAttribute, không thể được xây dựng đúng cách. Tôi muốn quản lý nó trên mức ràng buộc mà thôi.

Trả lời

17

Bạn có thể thay đổi hành vi tiêm bằng cách liên kết bằng cách sử dụng phương pháp nhà máy (ví dụ: ToMethod) và có thể cho phép nhập null bằng cách định cấu hình cài đặt AllowNullInjection của vùng chứa.

Một giải pháp thay thế khác là sử dụng phương pháp nhà máy và cung cấp đối tượng giả nhẹ thay vì lớp cân nặng của bạn. Nếu bạn đang sử dụng giao diện, điều này sẽ đơn giản, chỉ cần triển khai giao diện không làm gì cả. Bạn thậm chí có thể sử dụng một khuôn khổ nhạo báng như FakeItEasy để xây dựng những núm vú giả này cho bạn. Lợi ích ở đây, là hình nộm làm cho các hành vi đặc biệt trong suốt đối với các khách hàng tức là khách hàng không cần phải kiểm tra xem có null vv

Một ví dụ của việc sử dụng một phương pháp nhà máy, cộng với AllowNullInjection và null:

public void Configure() 
{ 
    bool create = true; 

    IKernel kernel = new StandardKernel(); 

    kernel.Settings.AllowNullInjection = true; 

    kernel.Bind<IFoo>().ToMethod(ctx => create ? ctx.Kernel.Get<Foo>() : null); 

    DependendsOnIFoo depFoo = kernel.Get<DependendsOnIFoo>(); 
} 

private interface IFoo {} 

private class Foo : IFoo {} 

private class DependendsOnIFoo 
{ 
    public DependendsOnIFoo(IFoo foo) {} 
} 

Và ví dụ về một vật thể nhẹ được thay thế tùy thuộc vào cờ:

public void Configure() 
{ 
    bool heavy = true; 

    IKernel kernel = new StandardKernel(); 

    kernel.Bind<IFoo>() 
    .ToMethod(ctx => heavy ? ctx.Kernel.Get<HeavyFoo>() : (IFoo)new DummyFoo()); 

    DependendsOnIFoo depFoo = kernel.Get<DependendsOnIFoo>(); 
} 

private interface IFoo {} 

private class HeavyFoo : IFoo {} 

private class DummyFoo : IFoo { } 

private class DependendsOnIFoo 
{ 
    public DependendsOnIFoo(IFoo foo) {} 
} 
12

Tiêm null thường không phải là ý tưởng khôn ngoan. Điều này sẽ gây ô nhiễm mã của bạn với kiểm tra nếu đối tượng là null hay không được thể hiện bằng đoạn mã sau:

public interface IFoo 
{ 
    void Do(); 
} 

public class Foo : IFoo 
{ 
    public void Do() 
    { 
     DoSomething(); 
    } 
} 

public class UglyNullCheckingBar 
{ 
    IFoo foo; 
    public Bar(IFoo foo) 
    { 
     this.foo = foo; 
    } 

    public void Do() 
    { 
     if (this.foo != null) 
     { 
      this.foo.Do(); 
     } 
    } 
} 

Cách tốt hơn trong trường hợp này là để thực hiện một đối tượng Null mà không hoàn toàn không có gì và tiêm này thay vì vô giá trị. Điều này giữ mã của bạn sạch sẽ.

public class NullFoo : IFoo 
{ 
    public void Do() {} 
} 

public class Bar 
{ 
    IFoo foo; 
    public Bar(IFoo foo) 
    { 
     this.foo = foo; 
    } 

    public void Do() 
    { 
     this.foo.Do(); 
    } 
} 
Các vấn đề liên quan