2013-02-03 12 views
6

Tôi muốn có một cá thể cho mỗi lần đăng ký phạm vi kết hợp phù hợp trong Autofac, nhưng đôi khi cần phải yêu cầu một cá thể từ một thùng chứa toàn cầu (nơi không có phạm vi thời gian phù hợp). Trong các trường hợp không tồn tại phạm vi thời gian phù hợp, tôi muốn đưa ra một cá thể cấp cao thay vì ném một ngoại lệ.Ví dụ cho mỗi phạm vi thời gian phù hợp, với mặc định?

Điều này có khả thi không?

+0

Tại sao bạn cần điều này? Bạn có muốn đăng ký toàn cầu khác với đăng ký phạm vi không? Hay bạn muốn người tiêu dùng nhận được một ví dụ trong một trường hợp và các trường hợp khác trong các trường hợp khác, trong khi các cấu hình vẫn giữ nguyên cho cả phạm vi toàn cầu và phạm vi được gắn thẻ? –

+0

@PavelGatilov Sau đó. Cùng một cấu hình, trường hợp khác nhau cho mỗi phạm vi được gắn thẻ và thể hiện khác nhau cho phạm vi toàn cầu. –

Trả lời

9

Tôi nghĩ bạn nên mở rộng Autofac bằng cách giới thiệu một lựa chọn cuộc đời mới. Tôi đã lấy nguồn Autofac và sửa đổi chúng một chút:

public static class RegistrationBuilderExtensions 
{ 
    public IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InstancePerMatchingOrRootLifetimeScope(this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> builder, params object[] lifetimeScopeTag) 
    { 
     if (lifetimeScopeTag == null) throw new ArgumentNullException("lifetimeScopeTag"); 
     builder.RegistrationData.Sharing = InstanceSharing.Shared; 
     builder.RegistrationData.Lifetime = new MatchingScopeOrRootLifetime(lifetimeScopeTag); 
     return builder; 
    } 
} 

public class MatchingScopeOrRootLifetime: IComponentLifetime 
{ 
    readonly object[] _tagsToMatch; 

    public MatchingScopeOrRootLifetime(params object[] lifetimeScopeTagsToMatch) 
    { 
     if (lifetimeScopeTagsToMatch == null) throw new ArgumentNullException("lifetimeScopeTagsToMatch"); 

     _tagsToMatch = lifetimeScopeTagsToMatch; 
    } 

    public ISharingLifetimeScope FindScope(ISharingLifetimeScope mostNestedVisibleScope) 
    { 
     if (mostNestedVisibleScope == null) throw new ArgumentNullException("mostNestedVisibleScope"); 

     var next = mostNestedVisibleScope; 
     while (next != null) 
     { 
      if (_tagsToMatch.Contains(next.Tag)) 
       return next; 

      next = next.ParentLifetimeScope; 
     } 

     return mostNestedVisibleScope.RootLifetimeScope; 
    } 
} 

Chỉ cần thêm các lớp này để dự án của bạn và đăng ký bạn thành phần như:

builder.RegisterType<A>.InstancePerMatchingOrRootLifetimeScope("TAG"); 

Tôi đã không thử nó bản thân mình, nhưng nó phải làm việc .

2

Giải pháp có thể là ghi đè đăng ký trong phạm vi thời gian sống của trẻ em.

mẫu:

public enum Scopes 
{ 
    TestScope 
} 

public class Test 
{ 
    public string Description { get; set; } 
} 

public class Tester 
{ 
    public void DoTest() 
    { 
     ContainerBuilder builder = new ContainerBuilder(); 
     builder.RegisterType<Test>() 
      .OnActivating(args => args.Instance.Description = "FromRoot") 
      .SingleInstance(); 
     var container = builder.Build(); 

     var scope = container.BeginLifetimeScope(Scopes.TestScope, b => b 
      .RegisterType<Test>() 
      .InstancePerMatchingLifetimeScope(Scopes.TestScope) 
      .OnActivating(args => args.Instance.Description = "FromScope")); 

     var test1 = container.Resolve<Test>(); 
     Console.WriteLine(test1.Description); //writes FromRoot 

     var test2 = scope.Resolve<Test>(); 
     Console.WriteLine(test2.Description); //writes FromScope 

     Console.ReadLine(); 
    } 
} 
+0

Trong khi mã có chút khó hiểu, @Memoizer là đúng - cách duy nhất để làm điều này là ghi đè đăng ký trong phạm vi con. Thật không may, câu hỏi đặt ra là "Tôi muốn một kiểu phạm vi trọn đời ở một nơi và một kiểu khác ở một nơi khác", không phải là kịch bản được hỗ trợ, vì vậy nó yêu cầu một số mã tùy chỉnh như thế này để làm cho nó xảy ra. –