Ok, tôi đã tìm ra một cách rất rõ ràng để thực hiện việc này!
Trước hết, chúng tôi cần triển khai IHandlerSelector
, điều này có thể chọn trình xử lý dựa trên ý kiến của chúng tôi về vấn đề hoặc vẫn trung lập (bằng cách trả lại null
, có nghĩa là "không có ý kiến").
/// <summary>
/// Emits an opinion about a component's lifestyle only if there are exactly two available handlers and one of them has a PerWebRequest lifestyle.
/// </summary>
public class LifestyleSelector : IHandlerSelector
{
public bool HasOpinionAbout(string key, Type service)
{
return service != typeof(object); // for some reason, Castle passes typeof(object) if the service type is null.
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
if (handlers.Length == 2 && handlers.Any(x => x.ComponentModel.LifestyleType == LifestyleType.PerWebRequest))
{
if (HttpContext.Current == null)
{
return handlers.Single(x => x.ComponentModel.LifestyleType != LifestyleType.PerWebRequest);
}
else
{
return handlers.Single(x => x.ComponentModel.LifestyleType == LifestyleType.PerWebRequest);
}
}
return null; // we don't have an opinion in this case.
}
}
Tôi đã đưa ra ý kiến rất hạn chế về mục đích. Tôi sẽ chỉ có ý kiến nếu có chính xác hai người xử lý và một trong số họ có lối sống PerWebRequest
; nghĩa là người kia là có thể là thay thế không phải HttpContext.
Chúng tôi cần đăng ký bộ chọn này với Castle. Tôi làm như vậy trước khi tôi bắt đầu đăng ký bất kỳ thành phần khác:
container.Kernel.AddHandlerSelector(new LifestyleSelector());
Cuối cùng Tôi ước gì có bất kỳ đầu mối như thế nào tôi có thể sao chép đăng ký của tôi để tránh tình trạng này:
container.Register(
AllTypes
.FromAssemblyContaining<EmailService>()
.Where(t => t.Name.EndsWith("Service"))
.WithService.Select(IoC.SelectByInterfaceConvention)
.LifestylePerWebRequest()
);
container.Register(
AllTypes
.FromAssemblyContaining<EmailService>()
.Where(t => t.Name.EndsWith("Service"))
.WithService.Select(IoC.SelectByInterfaceConvention)
.LifestylePerThread()
);
Nếu bạn có thể tìm ra một cách sao chép đăng ký, thay đổi lối sống và đăng ký cả hai (bằng cách sử dụng container.Register
hoặc IRegistration.Register
), vui lòng đăng câu trả lời ở đây! :)
Cập nhật: Trong thử nghiệm, tôi cần phải đặt tên duy nhất việc đăng ký giống hệt nhau, tôi đã làm như vậy như thế này:
.NamedRandomly()
public static ComponentRegistration<T> NamedRandomly<T>(this ComponentRegistration<T> registration) where T : class
{
string name = registration.Implementation.FullName;
string random = "{0}{{{1}}}".FormatWith(name, Guid.NewGuid());
return registration.Named(random);
}
public static BasedOnDescriptor NamedRandomly(this BasedOnDescriptor registration)
{
return registration.Configure(x => x.NamedRandomly());
}
Có một câu hỏi liên quan đến việc chạy mã trong nền của ứng dụng ASP.NET. Câu hỏi là về thùng chứa Simple Injector DI, nhưng câu trả lời vẫn có thể thú vị với bạn: http://stackoverflow.com/a/11059491/264697. – Steven