Vì vậy, cách lý tưởng để làm việc đó từ những gì Tôi đã đọc được tiêm một hạt nhân bất cứ khi nào bạn cần truy cập IOC ... cũng đó là tất cả tốt và tốt; chúng tôi giữ việc sử dụng SL ở mức tối thiểu.
Không, việc đưa hạt nhân vào các lớp học kinh doanh của bạn không phải là cách tốt nhất để thực hiện. Cách tốt hơn là tạo nhà máy, ví dụ: IFooFactory { IFoo Create(); }
hoặc Func<IFoo>
và để điều này tạo ra phiên bản mới.
Việc triển khai giao diện này đi vào gốc ghép, lấy một cá thể của hạt nhân và thực hiện giải quyết bằng cách sử dụng hạt nhân. Điều này giúp cho các lớp của bạn không có một vùng chứa cụ thể và bạn có thể tái sử dụng chúng trong một dự án khác bằng cách sử dụng một vùng chứa khác. Trong trường hợp của Func bạn có thể sử dụng mô-đun sau: Does Ninject support Func (auto generated factory)? Ninject 2.4 sẽ có hỗ trợ gốc cho việc này.
Theo như việc tái cấu trúc, bạn khó có thể cho bạn biết cách tốt nhất để đi mà không biết mã nguồn của ứng dụng của bạn là gì. Tôi chỉ có thể cung cấp cho bạn một approch rằng có lẽ có thể làm việc.
Tôi giả sử bạn muốn cấu trúc lại toàn bộ ứng dụng thành DI thích hợp trong thời gian dài. Những gì tôi đã làm một lần cho một dự án khá lớn (30-40 năm-người) là về những điều sau đây:
Bắt đầu tại gốc ghép và làm việc xuống cây đối tượng và thay đổi một lớp DI. Một khi bạn đạt đến tất cả các lá bắt đầu refactor tất cả các dịch vụ mà không phụ thuộc vào các dịch vụ khác và làm việc với lá của họ bằng cách sử dụng cùng một cách tiếp cận. Sau đó, tiếp tục với các dịch vụ chỉ phụ thuộc vào các dịch vụ đã được tái cấu trúc và lặp lại cho đến khi tất cả các dịch vụ được tái cấu trúc. Tất cả các bước này có thể được thực hiện sau khi các bước khác để mã liên tục được cải thiện trong khi các tính năng mới vẫn có thể được thêm cùng một lúc. Trong thời gian trung bình ServiceLocation là chấp nhận được, miễn là trọng tâm là làm cho nó đúng càng sớm càng tốt.
Pseudo mã ví dụ:
Foo{ ServiceLocator.Get<Service1>(), new Bar() }
Bar{ ServiceLocator.Get<IService1>(), ServiceLocator.Get<IService2>(), new Baz() }
Baz{ ServiceLocator.Get<IService3>() }
Service1 { ServiceLocator.Get<Service3>() }
Service2 { ServiceLocator.Get<Service3>() }
Service3 { new SomeClass()}
Bước 1 - Thay đổi Root (Foo)
Foo{ ctor(IService1, IBar) }
Bar{ ServiceLocator.Get<IService1>(), ServiceLocator.Get<IService2>(), new Baz() }
Baz{ ServiceLocator.Get<IService3>() }
Service1 { ServiceLocator.Get<IService2>() }
Service2 { ServiceLocator.Get<IService3>() }
Service3 { new SomeClass()}
Bind<IBar>().To<Bar>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bước 2 - Thay đổi phụ thuộc của rễ
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ServiceLocator.Get<IService3>() }
Service1 { ServiceLocator.Get<Service2>() }
Service2 { ServiceLocator.Get<Service3>() }
Service3 { new SomeClass()}
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bind<IService2>().ToMethod(ctx => ServiceLocator.Get<IService2>());
Bước 3 - Thay đổi phụ thuộc của họ và tiếp tục cho đến khi bạn đang ở trên lá
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ctor(IService3) }
Service1 { ServiceLocator.Get<Service2>() }
Service2 { ServiceLocator.Get<Service3>() }
Service3 { new SomeClass() }
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bind<IService2>().ToMethod(ctx => ServiceLocator.Get<IService2>());
Bind<IService3>().ToMethod(ctx => ServiceLocator.Get<IService3>());
Bước 4 - Refactor các dịch vụ mà không phụ thuộc vào những người khác
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ctor(IService3) }
Service1 { ServiceLocator.Get<Service2>() }
Service2 { ServiceLocator.Get<Service3>() }
Service3 { ctor(ISomeClass) }
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<ISomeClass>().To<SomeClass>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bind<IService2>().ToMethod(ctx => ServiceLocator.Get<IService2>());
Bind<IService3>().To<Service3>().InSingletonScope();
Bước 5 - Refactor Tiếp theo những người phụ thuộc vào dịch vụ mà chỉ có dịch vụ refactored như phụ thuộc.
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ctor(IService3) }
Service1 { ServiceLocator.Get<Service2>() }
Service2 { ctor(IService3) }
Service3 { ctor(ISomeClass) }
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<ISomeClass>().To<SomeClass>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bind<IService2>().To<Service2>().InSingletonScope();
Bind<IService3>().To<Service3>().InSingletonScope();
Bước 6 - Lặp lại cho đến khi mọi dịch vụ được tái cấu trúc.
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ctor(IService3) }
Service1 { ctor(IService2) }
Service2 { ctor(IService3) }
Service3 { ctor(ISomeClass) }
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<ISomeClass>().To<SomeClass>();
Bind<IService1>().To<Service1>().InSingletonScope();
Bind<IService2>().To<Service2>().InSingletonScope();
Bind<IService3>().To<Service3>().InSingletonScope();
Có thể bạn muốn chuyển sang cấu hình vùng chứa dựa trên quy ước cùng với việc tái cấu trúc. Trong trường hợp này, tôi sẽ thêm một thuộc tính cho tất cả các lớp đã được cấu trúc lại để đánh dấu chúng và loại bỏ nó một lần nữa sau khi tất cả việc tái cấu trúc được thực hiện. Trong các quy ước, bạn có thể sử dụng thuộc tính này để lọc tất cả các lớp được cấu trúc lại.
Với mức độ chi tiết bạn đã đưa ra, tất cả những gì tôi có thể nói là đọc các câu trả lời hàng đầu của @Mark Seeman và sau đó quay lại và cung cấp một số chi tiết có liên quan về lý do tại sao bạn cảm thấy cần nhiều hạt nhân giai đoạn trong quá trình tái cấu trúc) mà bạn có nhiều Root Roots.Ngay bây giờ câu hỏi là quá mở cho bất cứ ai để trả lời và cảm thấy họ đang thêm một cái gì đó đáng giá mà chưa được bao gồm trong các bài viết nói trên –
thêm một số chi tiết – ryber