2015-07-15 15 views
8

Container Unity sẽ tự động giải quyết bất kỳ loại nào mà nó có thể tự mình tìm ra mà không cần đăng ký thủ công. Đó là tốt trong một số cách, nhưng vấn đề tôi có là nó sử dụng một TransientLifetimeManager cho loại độ phân giải, trong khi tôi hầu như luôn luôn muốn có một ContainerControlledLifetimeManager. Tôi vẫn có thể đăng ký các loại của tôi như là thủ công, tất nhiên, nhưng nếu tôi quên, thay vì nhận được một ngoại lệ unhandled lúc khởi động, ứng dụng sẽ khởi chạy thành công và mọi thứ sẽ xuất hiện để làm việc. Nhưng cuối cùng sẽ có các lỗi, có thể là những lỗi rất khó, có thể chẩn đoán được, do thực tế là có nhiều trường hợp của một loại có nghĩa là một singleton. Vì vậy, câu hỏi của tôi là: Có cách nào tôi có thể chỉ định trình quản lý toàn thời gian mặc định khác hoặc tắt hoàn toàn hành vi tự động mặc định và giới hạn vùng chứa cho loại tôi đăng ký bản thân mình (trực tiếp hoặc theo quy ước của riêng tôi) không? Không.Unity: Thay đổi mặc định quản lý suốt đời cho đăng ký ngầm và/hoặc vô hiệu hóa chúng

+0

Bản sao có thể có của http://stackoverflow.com/questions/29828410/default-the-lifetimemanager-to-the-singleton-manager-containercontrolledlifetim – gastonmancini

+0

Tuyệt vời; dường như cho tôi một cách để đặt 'LifetimeManager' mặc định. Tôi vẫn muốn biết nếu có một cách để vô hiệu hóa đăng ký tự động/tiềm ẩn quá. – dlf

Trả lời

5

Có cách nào tôi có thể chỉ định một khác nhau quản lý đời mặc định

Có, bạn có thể sử dụng một phần mở rộng container mà sẽ sử dụng một trình quản lý cuộc đời khác nhau. Xem Request for configurable default lifetimemanager để biết ví dụ.

hoặc vô hiệu hóa hành vi mặc định tự động có độ phân giải hoàn toàn và hạn chế các container để loại tôi đăng ký bản thân mình

Vâng, một phần mở rộng container có thể làm được điều này là tốt.

Trước tiên trong khi đăng ký rõ ràng, hãy ghi lại BuildKey của đăng ký. Sau đó, trước khi tạo đối tượng kiểm tra xem BuildKey đã được đăng ký một cách rõ ràng chưa.

public class RegistrationTrackingExtension : UnityContainerExtension 
{ 
    private ConcurrentDictionary<NamedTypeBuildKey, bool> registrations = 
     new ConcurrentDictionary<NamedTypeBuildKey, bool>(); 

    protected override void Initialize() 
    { 
     base.Context.Registering += Context_Registering; 
     base.Context.Strategies.Add(
      new ValidateRegistrationStrategy(this.registrations), UnityBuildStage.PreCreation); 
    } 

    private void Context_Registering(object sender, RegisterEventArgs e) 
    { 
     var buildKey = new NamedTypeBuildKey(e.TypeTo, e.Name); 
     this.registrations.AddOrUpdate(buildKey, true, (key, oldValue) => true); 
    } 

    public class ValidateRegistrationStrategy : BuilderStrategy 
    { 
     private ConcurrentDictionary<NamedTypeBuildKey, bool> registrations; 

     public ValidateRegistrationStrategy(ConcurrentDictionary<NamedTypeBuildKey, bool> registrations) 
     { 
      this.registrations = registrations; 
     } 

     public override void PreBuildUp(IBuilderContext context) 
     { 
      if (!this.registrations.ContainsKey(context.BuildKey)) 
      { 
       Exception e = new Exception("Type was not explicitly registered in the container."); 
       throw new ResolutionFailedException(context.BuildKey.Type, context.BuildKey.Name, e, context); 
      } 
     } 
    } 
} 

Sau đó thêm tiện ích, đăng ký một số lớp và giải quyết. Nếu lớp học không được đăng ký một cách rõ ràng thì một ngoại lệ sẽ bị ném.

IUnityContainer container = new UnityContainer(); 
// Add container extension 
container.AddNewExtension<RegistrationTrackingExtension>(); 

// Register types 
container.RegisterType<MyClass>(); 
container.RegisterType<IMyClass, MyClass>(); 
container.RegisterType<IMyClass, MyClass>("A"); 

// These succeed because they were explicitly registered 
container.Resolve<IMyClass>(); 
container.Resolve<IMyClass>("A"); 
container.Resolve<MyClass>(); 

// MyClass2 was not registered so this will throw an exception 
container.Resolve<MyClass2>(); 
+1

Tuyệt vời; cả hai giải pháp đều hoạt động hoàn hảo. Và 'RegistrationTrackingExtension' đã xác định một số lỗi trong ứng dụng! – dlf

1

Tôi đã thử DefaultLifetimeManegerExtension nhưng bằng cách nào đó nó không hoạt động. (Có lẽ Unity đã thay đổi?). Dù sao nếu bạn không muốn sử dụng một phần mở rộng, bạn cũng có thể sử dụng tính năng RegsiterByConvention.

container.RegisterTypes(AllClasses.FromLoadedAssemblies(), WithMappings.None, WithName.Default, x => new DisposingTransientLifetimeManager()); 

Điều này sẽ đăng ký tất cả các Lớp với "DisposingTransientLifetimeManager" mà tôi đã chọn để sử dụng làm mặc định. Lưu ý rằng bạn nên thực hiện việc này khi bắt đầu đăng ký vì tất cả đăng ký sẽ ghi đè mọi đăng ký trước đó của cùng Loại và Tên.

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