Resolving Generic Interface with Autofac

前端 未结 2 1207
难免孤独
难免孤独 2020-12-02 15:48

Given the following code, how do I resolve the right SomeInstance in autofac?

public class BaseClass {}

public class SubClass1 : BaseClass {}

public class          


        
相关标签:
2条回答
  • 2020-12-02 16:02

    Autofac supports open generics. You can use the following code if generics type is known at compile time:

    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);
    

    If type parameter is not known until runtime (which is likely your case if you want to iterate through collection of types) then you can build your type using MakeGenericType:

            var typeInRuntime = typeof (SubClass1);
            var instance1 = container.Resolve(typeof(IGenericInterface<>).MakeGenericType(typeInRuntime));
    
    0 讨论(0)
  • 2020-12-02 16:12

    Correction. You cannot call MakeGenericType from the Container. I solved the issue of instantiating Generics using the 'TYPE' as the parameter on the Resolve call. The builder is registered.

            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);
                }
            });
    

    Then the resolution happens like this, passing a TypedParameter to the Resolve. In this case I have a list of items (IItem) that are resolved that I want to create a repository for all of the items of that type.

            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);
            }
    

    Thanks for your post it helped and I Hope this update helps.

    0 讨论(0)
提交回复
热议问题