Tôi đang sử dụng thư viện lớp học có thể được sử dụng lại bởi các thành phần khác. Trong thư viện lớp này, tôi đang sử dụng sự thống nhất cho việc tiêm phụ thuộc. Đối với thư viện lớp này, tôi tạo một dự án thử nghiệm. Người gọi cũng nhận được một dự án thử nghiệm. Một điều tôi không chắc chắn là vị trí của các ràng buộc. Tôi có nên kết hợp điều này trong thư viện lớp hay tôi nên làm điều này từ ứng dụng gọi điện?IoC trong thư viện lớp học. Nơi để bootstrap
Trả lời
Đây là một vấn đề thú vị. Làm thế nào bạn có thể phụ thuộc tiêm hội đồng tái sử dụng mà không có một điểm vào. Tôi thực sự muốn xem câu trả lời của người khác.
Tiêm phụ thuộc là trách nhiệm của lắp ráp điểm vào. Tuy nhiên, nếu bạn có rất nhiều lớp học và hội đồng mỗi cần DI, thì có thể là chúng bị bỏ lại cho một số lớp học/hội đồng và nhiệm vụ trở nên nguy hiểm.
Giải pháp Một
Sử dụng quy ước trên cấu hình. Bạn tuân theo quy tắc của lớp Foo
triển khai IFoo
, v.v. Rất nhiều khung công tác DI có phương tiện để thiết lập quy tắc sử dụng quy ước.
Giải pháp hai
Giải pháp trên không giải quyết được tất cả các vấn đề vì đôi khi bạn cần phải tham số hóa việc thiết lập tiêm. Dưới đây là cách tôi đã giải quyết vấn đề (đặc biệt là đối với những assembly được nạp bởi MEF và điều này là dành cho AutoFac
):
Tạo một giao diện IIocInstaller
nơi container (hoặc người xây dựng được thông qua)
public interface IIocInstaller
{
void Setup(ContainerBuilder builder);
}
Đã tạo thuộc tính assembly để gắn cờ các hội đồng cần DI:
[AttributeUsage(AttributeTargets.Assembly)]
public class ExportAssemblyAttribute : Attribute
{
}
Trong mỗi lắp ráp, tôi tạo ra một lớp mà thiết lập DI:
[assembly: ExportAssembly]
namespace This.That
{
[Export(typeof(IIocInstaller))]
public class IocInstaller : IIocInstaller
{
public void Setup(ContainerBuilder builder)
{
....
}
}
}
Sau đó, trong thời điểm nhập cảnh, tôi có một mã chung mà trông qua tất cả các assembly được nạp (kể cả MEFed) có thuộc tính lắp ráp và sau đó tìm loại triển khai IIocInstaller
và sau đó gọi Thiết lập trên chúng.
Cảm ơn đề xuất. Nó đưa tôi ra khỏi khuôn mẫu suy nghĩ của tôi. Chúng tôi hiện đang giới thiệu một dự án thiết lập riêng biệt. Bằng cách này, thư viện lớp có thể sử dụng các triển khai khác nhau. – Patrick
@Patrick đó là một vấn đề khó khăn. Các nhà xây dựng tĩnh không nhất thiết phải làm việc vì nó có thể bị trễ cho DI, đặc biệt là đối với các thùng chứa hai bước như AutoFac. – Aliostad
Đầu tiên đây là một phản ứng howto Autofac với câu hỏi Unity. Ngoài ra có một thư viện hỗ trợ nhiều IoC/DI container không nên khó khăn nếu các container hỗ trợ các phần mở rộng khái niệm theo cách tương tự như Unity. Bạn sẽ chỉ có một lớp mở rộng dành riêng sử dụng vùng chứa của trình triển khai IoC/DI và sau đó ứng dụng điểm vào có thể chọn phần mở rộng phù hợp với lựa chọn IoC/DI của họ. –
Thực hiện việc này từ ứng dụng gọi điện sẽ đặt thêm gánh nặng cho ứng dụng gọi điện. Rời khỏi cơ hội để bỏ qua việc khởi tạo và gặp rắc rối.
Tôi sẽ làm điều đó trong thư viện lớp, ví dụ như trong một hàm tạo tĩnh.
Đó không phải là lựa chọn khôn ngoan. Ứng dụng entry-point nên sở hữu và kiểm soát container, đó là lý do tại sao sự thống nhất cho phép đăng ký các phần mở rộng và lớp cơ sở UnityContainerExtension để làm cho nó dễ dàng thực hiện giao diện IUnityContainerExtensionConfigurator. Xem câu trả lời của tôi cho một ví dụ. –
Tôi biết rằng câu trả lời đã được chọn, tuy nhiên tôi nghĩ rằng một phần của Unity đang bị bỏ qua. Vì đây là một câu hỏi Unity cụ thể, tôi nghĩ tôi chỉ ra lớp cơ sở UnityContainerExtension triển khai IUnityContainerExtensionConfigurator. Thư viện API này có thể mở rộng để dễ dàng cho ứng dụng nhập điểm sở hữu Vùng chứa để đảm bảo thư viện của bạn được đăng ký đúng với Vùng chứa và cho phép chủ sở hữu API kiểm soát những gì được đăng ký và làm sao.
Điều này được sử dụng bởi Thư viện doanh nghiệp của Microsoft cho mục đích này.
Tôi sẽ sử dụng một thư viện Logging như một đơn giản:
public class LoggingUnityExtension : UnityContainerExtension
{
protected override void Initialize()
{
Container.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());
}
}
Sau đó ứng dụng vào điểm thực hiện điều này:
public class Bootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.AddNewExtension<EnterpriseLibraryCoreExtension>();
Container.AddNewExtension<LoggingUnityExtension>();
// ...
}
// ...
}
Bây giờ họ đã đăng ký Thư viện Doanh nghiệp và các API cho các Thư viện ghi nhật ký. Nó rất đơn giản cho ứng dụng entry-point với phương thức này, đó là những gì mà bất kỳ nhà phát triển thư viện nào cũng nên có như một mục tiêu.
Có thể muốn tham khảo thư viện để mọi người có thể sử dụng ví dụ của bạn một cách dễ dàng. Bạn có cần 'EnterpriseLibraryCoreExtension' để làm việc này không? – ajbeaven
Điều đó phụ thuộc vào nhu cầu của bạn, nhưng thông thường khi bạn sử dụng Unity và bất kỳ khối EntLib nào, bạn sẽ cần sử dụng nó hầu như luôn luôn. Hãy nhớ rằng đây là các đoạn mã để hiển thị các ví dụ không phải là mã đầy đủ chức năng. Tôi đưa ra ý kiến của tôi rằng tôi đang sử dụng Thư viện Doanh nghiệp của Microsoft mà phải đủ cho ví dụ. Đối với ILogger và Logger, chúng chỉ được sử dụng để chỉ cách sử dụng phần mở rộng của thùng chứa không chỉ cho bạn cách tạo một Logger. Việc triển khai đó không liên quan. –
O.K Tạo thư viện có tên Project.Ioc. Cài đặt Unity tại đây. Tham khảo các lớp khác với thư viện Ioc. Và Ioc Library để trình bày lớp. Tạo một lớp có tên là UnityHelper.
/// <summary>
/// Bind the given interface in request scope
/// </summary>
public static class IocExtensions
{
public static void BindInRequestScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new HierarchicalLifetimeManager());
}
public static void BindInSingletonScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new ContainerControlledLifetimeManager());
}
}
/// <summary>
/// The injection for Unity
/// </summary>
public static class UnityHelper
{
public static IUnityContainer Start()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new Unity.Mvc4.UnityDependencyResolver(container));
return container;
}
/// <summary>
/// Inject
/// </summary>
/// <returns></returns>
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// Database context, one per request, ensure it is disposed
container.BindInRequestScope<IMVCForumContext, MVCForumContext>();
container.BindInRequestScope<IUnitOfWorkManager, UnitOfWorkManager>();
//Bind the various domain model services and repositories that e.g. our controllers require
container.BindInRequestScope<ITopicService, TopicService>();
container.BindInRequestScope<ITopicTagRepository, TopicTagRepository>();
//container.BindInRequestScope<ISessionHelper, SessionHelper>();
return container;
}
}
Kiểm tra dự án MvcForum. Có thư viện lớp MvcForm.Ioc. Thư viện nhận các tham chiếu Lớp khác. Chỉ có một lớp có tên là UnityHelper.
https://github.com/leen3o/mvcforum
tôi hy vọng đây là wat bạn đang tìm kiếm.
Bạn có thể xem [Thư viện doanh nghiệp của p & p] (http://entlib.codeplex.com). Họ đang sử dụng Unity dưới bìa và vùng chứa được khởi tạo mà không có sự tương tác của người dùng. –
@ Sebastian, điều đó không hoàn toàn đúng với ứng dụng điểm vào (còn gọi là người dùng) phải khởi tạo một vùng chứa và đăng ký phần mở rộng hợp nhất thư viện doanh nghiệp. Xem câu trả lời của tôi cho một ví dụ về điều này dưới đây. –