2010-04-26 35 views
14

Làm cách nào để xử lý các lớp có phương thức tĩnh bằng Ninject?Làm cách nào để xử lý các lớp với các phương thức tĩnh bằng Ninject?

Tức là, trong C# người ta không thể có phương pháp tĩnh trong giao diện và Ninject hoạt động trên cơ sở sử dụng giao diện?

Trường hợp sử dụng của tôi là một lớp học mà tôi muốn nó có phương pháp tĩnh để tạo ra một ví dụ chưa được tự động hóa của chính mình .

EDIT 1

Chỉ cần thêm một ví dụ trong lớp TopologyImp, trong phương pháp() GetRootNodes, thế nào tôi sẽ tạo ra một số lớp inode để trở lại? Tôi sẽ xây dựng chúng với thực hành mã bình thường hay tôi bằng cách nào đó sẽ sử dụng Ninject? Nhưng nếu tôi sử dụng các container để tạo ra sau đó tôi đã không cho kiến ​​thức thư viện này của IOC sau đó?

public interface ITopology 
{ 
    List<INode> GetRootNodes(); 
} 


public class TopologyImp : ITopology 
{ 
    public List<INode> GetRootNodes() 
    { 
     List<INode> result = new List<INode>(); 

     // Need code here to create some instances, but how to without knowledge of the container? 
     // e.g. want to create a few INode instances and add them to the list and then return the list 
    } 
} 

public interface INode 
{ 
    // Parameters 
    long Id { get; set; } 
    string Name { get; set; } 
} 

class NodeImp : INode 
{ 
    public long Id 
    { 
     get { throw new NotImplementedException(); } 
     set { throw new NotImplementedException(); } 
    } 

    public string Name 
    { 
     get { throw new NotImplementedException(); } 
     set { throw new NotImplementedException(); } 
    } 
} 


// Just background to highlight the fact I'm using Ninject fine to inject ITopology 
public partial class Form1 : Form 
{ 
    private ITopology _top; 
    public Form1() 
    { 
     IKernel kernal = new StandardKernel(new TopologyModule()); 
     _top = kernal.Get<ITopology>(); 
     InitializeComponent(); 
    } 
} 

Trả lời

9

Nếu bạn đang xây dựng một singleton hoặc một cái gì đó có tính chất đó và cố gắng để tiêm phụ thuộc, thường bạn thay vì viết mã của bạn như là một lớp bình thường, mà không cần cố gắng để đưa vào rất nhiều (có thể không chính xác) mã quản lý singleton và thay vào đó đăng ký đối tượng InSingletonScope (v2 - bạn đã không đề cập đến phiên bản Ninject của bạn). Mỗi khi bạn làm điều đó, bạn có một lớp ít hơn mà không bề mặt phụ thuộc của nó.

Nếu bạn cảm thấy đặc biệt đẫm máu và chắc chắn rằng bạn muốn chống lại luồng chung đó, các công cụ chính Ninject cung cấp cho bạn là Kernel.Inject, cái mà bạn có thể sử dụng sau khi bạn (hoặc người khác) có new một trường hợp để tiêm các phụ thuộc. Nhưng sau đó để xác định vị trí của một hạt nhân bạn thường sẽ sử dụng một Service Locator, có khả năng gây ra nhiều mớ hỗn độn vì nó có khả năng giải quyết.

CHỈNH SỬA: Cảm ơn bạn đã theo dõi - Tôi thấy những gì bạn đang theo dõi. Đây là một cách hacky để xấp xỉ the autofac automatic factory mechanism: -

/// <summary> 
/// Ugly example of a not-very-automatic factory in Ninject 
/// </summary> 
class AutomaticFactoriesInNinject 
{ 
    class Node 
    { 
    } 

    class NodeFactory 
    { 
     public NodeFactory(Func<Node> createNode) 
     { 
      _createNode = createNode; 
     } 

     Func<Node> _createNode; 
     public Node GenerateTree() 
     { 
      return _createNode(); 
     } 
    } 

    internal class Module : NinjectModule 
    { 
     public override void Load() 
     { 
      Bind<Func<Node>>().ToMethod(context =>() => Kernel.Get<Node>()); 
     } 
    } 

    [Fact] 
    public void CanGenerate() 
    { 
     var kernel = new StandardKernel(new Module()); 
     var result = kernel.Get<NodeFactory>().GenerateTree(); 
     Assert.IsType<Node>(result); 
    } 
} 

Những thứ ToMethod là một ứng dụng cụ thể của mô hình ToProvider - đây là cách bạn muốn làm điều tương tự qua đường rằng: -

... 

    class NodeProvider : IProvider 
    { 
     public Type Type 
     { 
      get { return typeof(Node); } 
     } 
     public object Create(IContext context) 
     { 
      return context.Kernel.Get<Node>(); 
     } 
    } 

    internal class Module : NinjectModule 
    { 
     public override void Load() 
     { 
      Bind<Func<Node>>().ToProvider<NodeProvider>(); 
     } 
    } 

    ... 

Tôi đã không nghĩ điều này thông qua mặc dù và không đề xuất này như là một ý tưởng tốt - có thể có những cách tốt hơn để cấu trúc một cái gì đó như thế này. @Mark Seemann? : P

Tôi tin rằng Unity và MEF cũng hỗ trợ điều theo hướng này (từ khóa: máy tự động, Func)

EDIT 2: Cú pháp ngắn hơn nếu bạn sẵn sàng để sử dụng các thuộc tính chứa cụ thể và thả để tiêm bất động sản (ngay cả khi Ninject phép bạn ghi đè các thuộc tính cụ thể, tôi rất thích constructor injection):

class NodeFactory 
    { 
     [Inject] 
     public Func<Node> NodeFactory { private get; set; } 
     public Node GenerateTree() 
     { 
      return NodeFactory(); 
     } 
    } 

EDIT 3: bạn cũng cần phải nhận thức được this Ninject Module by @Remo Gloor which is slated to be in the 2.4 release

EDIT 4: Ngoài ra chồng chéo, nhưng không dir ectly có liên quan là một thực tế rằng trong Ninject, bạn có thể yêu cầu một số IKernel trong ctor/tài sản của bạn và có tiêm (nhưng điều đó không làm việc trực tiếp trong một phương pháp tĩnh).

+0

Xin chào Ruben - Tôi đã thêm một số làm rõ cho câu hỏi. Làm thế nào bạn sẽ tạo ra các trường hợp INode mình trong trường hợp này? (I E.xem điểm này trong mã mà tôi đã nhận xét) - cảm ơn – Greg

+0

@Greg: Điều này có tốt không? –

+0

Cảm ơn Ruben- Tôi sẽ phải để nó chìm vào. Tôi đang suy nghĩ về những lợi ích hữu hình mà cách tiếp cận này thực sự sẽ chỉ tạo ra các lớp bình thường tại chỗ tôi đã chỉ ra trong mã của mình? Bạn có thấy không? Giống như nó sẽ thực sự phá vỡ khái niệm IOC lưu ý trong tất cả các lĩnh vực khác của mã của bạn, bạn đã làm theo các phương pháp tiếp cận Ninject? – Greg

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