2009-07-27 27 views
28

Với mã sau, làm cách nào để giải quyết quyền SomeInstance trong autofac?Giải quyết giao diện chung với Autofac

public class BaseClass {} 

public class SubClass1 : BaseClass {} 

public class SubClass2 : BaseClass {} 

public interface IGenericInterface<T> where T : BaseClass {} 

public class SomeInstance1<T> : IGenericInterface<T> where T : SubClass1 

public class SomeInstance2<T> : IGenericInterface<T> where T : SubClass2 

Tôi muốn chọn SomeInstance1 hoặc 2 dựa trên loại của lớp chung trên các lớp con.

Vì vậy, ví dụ tôi có một tập hợp các lớp con (SubClass1, 2 ....) và trong khi lặp lại chúng tôi muốn chọn lớp SomeInstance phù hợp.

Trả lời

59

Autofac hỗ trợ Generics mở. Bạn có thể sử dụng đoạn mã sau nếu Generics loại được biết đến tại thời gian biên dịch:

var builder = new ContainerBuilder(); 

builder.RegisterGeneric(typeof(SomeInstance1<>)) 
    .As(typeof(IGenericInterface<>));    

var container = builder.Build(); 

var instance1 = container.Resolve<IGenericInterface<SubClass1>>(); 

Assert.IsInstanceOfType(typeof(SomeInstance1<SubClass1>), instance1); 

Nếu tham số kiểu không biết cho đến khi thời gian chạy (mà rất có thể trường hợp của bạn nếu bạn muốn lặp qua bộ sưu tập các loại) sau đó bạn có thể xây dựng loại của bạn bằng cách sử dụng MakeGenericType:

 var typeInRuntime = typeof (SubClass1); 
     var instance1 = container.Resolve(typeof(IGenericInterface<>).MakeGenericType(typeInRuntime)); 
1

Chỉnh sửa. Bạn không thể gọi MakeGenericType từ Container. Tôi đã giải quyết vấn đề khởi tạo Generics bằng cách sử dụng 'TYPE' làm tham số trên cuộc gọi Resolve. Người xây dựng được đăng ký.

 builder.RegisterGeneric(typeof (FakeRepository<>)).As(typeof (IRepository<>)).OnActivating(e => 
     { 
      var typeToLookup = e.Parameters.FirstOrDefault() as TypedParameter; 
      if (typeToLookup != null) 
      { 
       var respositoryType = typeof (FakeRepository<>); 
       Type[] typeArgs = {typeToLookup.Value.GetType()}; 
       var genericType = respositoryType.MakeGenericType(typeArgs); 
       var genericRepository = Activator.CreateInstance(genericType); 
       e.ReplaceInstance(genericRepository); 
      } 
     }); 

Sau đó, độ phân giải xảy ra như thế này, chuyển TypedParameter đến Resolve. Trong trường hợp này, tôi có một danh sách các mục (IItem) được giải quyết rằng tôi muốn tạo một kho lưu trữ cho tất cả các mục thuộc loại đó.

 var items = container.Resolve<IEnumerable<IItem<string>>>(); 
     foreach (var item in items) 
     { 
      var repository = container.Resolve(typeof (IRepository<DataItemBase>), new TypedParameter(item.GetType(), item)); 
      Assert.IsNotNull(repository); 
     } 

Cảm ơn bài đăng của bạn đã hữu ích và tôi hy vọng bản cập nhật này sẽ hữu ích.

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