如何在提前未知类型时向Autofac注册泛型依赖实例?
解决方案
要实现需求,你需要借助Autofac的ContainerBuilder,将手动创建的实例注册为对应泛型接口的单例,同时注册Test和Test1类型以便Autofac解析它们。具体步骤如下:
- 创建ContainerBuilder实例:用于构建依赖注入容器。
- 注册手动实例为对应泛型接口的单例:
- 对于
instance1(Foo<string, string>类型),通过typeof(IFoo<,>).MakeGenericType(...)生成对应的IFoo<string, string>接口类型。 - 使用
RegisterInstance方法注册实例,并用As指定要暴露的接口,最后调用SingleInstance()标记为单例。
- 对于
- 注册Test和Test1类型:让Autofac能够解析这两个类的实例。
- 构建容器并解析实例:验证注入是否生效。
修改后的完整代码如下:
using Autofac; void Main() { var builder = new ContainerBuilder(); string type1 = "System.String"; string type2 = "System.String"; Type fooType = typeof(Foo<,>).MakeGenericType(Type.GetType(type1), Type.GetType(type2)); ConstructorInfo ctor = fooType.GetConstructors().FirstOrDefault(); var instance1 = ctor.Invoke(new object[] { 1, 2 }); // 注册instance1为IFoo<string, string>的单例 Type fooInterfaceType = typeof(IFoo<,>).MakeGenericType(Type.GetType(type1), Type.GetType(type2)); builder.RegisterInstance(instance1).As(fooInterfaceType).SingleInstance(); type1 = "System.Int32"; type2 = "System.Int32"; fooType = typeof(Foo<,>).MakeGenericType(Type.GetType(type1), Type.GetType(type2)); ctor = fooType.GetConstructors().FirstOrDefault(); var instance2 = ctor.Invoke(new object[] { 1, 2 }); // 注册instance2为IFoo<int, int>的单例 fooInterfaceType = typeof(IFoo<,>).MakeGenericType(Type.GetType(type1), Type.GetType(type2)); builder.RegisterInstance(instance2).As(fooInterfaceType).SingleInstance(); // 注册Test和Test1类型 builder.RegisterType<Test>().AsSelf(); builder.RegisterType<Test1>().AsSelf(); // 构建容器 using var container = builder.Build(); // 解析Test并验证注入的实例 var test = container.Resolve<Test>(); test._param1.Print(); // 输出:Foo`2[System.String,System.String] // 解析Test1并验证注入的实例 var test1 = container.Resolve<Test1>(); test1._param1.Print(); // 输出:Foo`2[System.Int32,System.Int32] } // 以下是原定义的类型,保持不变 public interface IFoo<Tkey,Tvalue> { void Print(); } public class Foo<Tkey, Tvalue> : IFoo<Tkey, Tvalue> { private int _a ; private int _b ; public Foo(int a, int b) { this._a = a; this._b = b; } public void Print() { Console.WriteLine(this.GetType()); } } public interface ITest {} public class Test : ITest { public IFoo<string, string> _param1; // 修改为public方便验证,实际项目建议保持private public Test(IFoo<string, string> param1) { this._param1 = param1; } } public class Test1 : ITest { public IFoo<int, int> _param1; // 修改为public方便验证 public Test1(IFoo<int, int> param1) { this._param1 = param1; } }
关键说明:
- 注册实例到接口:因为
Test依赖的是IFoo<string, string>而非具体的Foo<string, string>,所以必须通过As(fooInterfaceType)将实例关联到对应的接口类型,这样Autofac在解析Test时才能找到匹配的依赖。 - SingleInstance():确保该实例在容器生命周期内是单例,所有依赖该类型的地方都会注入同一个实例。
- 注册Test/Test1:必须将这两个类注册到容器中,Autofac才能为它们解析构造函数中的依赖。
内容的提问来源于stack exchange,提问作者loneshark99
相关产品推荐
相关产品推荐

