You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在提前未知类型时向Autofac注册泛型依赖实例?

解决方案

要实现需求,你需要借助Autofac的ContainerBuilder,将手动创建的实例注册为对应泛型接口的单例,同时注册Test和Test1类型以便Autofac解析它们。具体步骤如下:

  1. 创建ContainerBuilder实例:用于构建依赖注入容器。
  2. 注册手动实例为对应泛型接口的单例:
    • 对于instance1(Foo<string, string>类型),通过typeof(IFoo<,>).MakeGenericType(...)生成对应的IFoo<string, string>接口类型。
    • 使用RegisterInstance方法注册实例,并用As指定要暴露的接口,最后调用SingleInstance()标记为单例。
  3. 注册Test和Test1类型:让Autofac能够解析这两个类的实例。
  4. 构建容器并解析实例:验证注入是否生效。

修改后的完整代码如下:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:24:27