如何使用Autofac解析接口并在类中使用它

时间:2019-05-13 11:23:29

标签: c# autofac

我正在尝试解决我在Autofac中注册的接口,但似乎无法正常工作。有 nullreferenceexception。

我注册接口的类:

    public void RegisterAutofac(HttpConfiguration config)
    {
        var builder = new ContainerBuilder();

        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

           (...)
        builder.RegisterType<ApiFileTester>().As<IApiFlTester>().InstancePerRequest();

        var container = builder.Build();
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

    }

然后我要在课堂上使用它:

  public class ApiFileSendingController : ApiClientBase
{
    private readonly IApiFlTester _apiFileTester;

    public ApiFileSendingController(DTO dto, IApiFlTester tester) : base(dto)
    {
        _tester = tester; 
    }


    public void Send(List<AftInvFileDTO> filesToSendRetry = null)
    {
        _apiFileTester.RegisterTestingMethods();
    }

}

然后在其他一些班上:

DTO dto = new DTO(); //some configuration here

ApiFileSendingController sender = new ApiFileSendingController(dto, null);
sender.Send(); 

这里有一个问题,因为我的界面为空。我试图这样传递它:

  

ApiFileSendingController发送者=新的ApiFileSendingController(dto,   null);

,但它为null,并且是完全合理的(我通过了null)。 是否可以配置可选参数?我想让这个界面通过autofac自动解决,而不是手动解决。

2 个答案:

答案 0 :(得分:0)

在解决您的课程时,我似乎没有问题。从技术上讲,不可能真正回答您的问题,因为该代码甚至无法编译,并且看来您丢失了大量的autofac注册。

Working Example

// @nuget: Autofac
using System;
using Autofac;

public class Program
{
    private static IContainer _container;

    public static void Main()
    {
        RegisterAutofac();
        using (var httpRequestScope = _container.BeginLifetimeScope("AutofacWebRequest"))
        {
            var apiController = httpRequestScope.Resolve<ApiFileSendingController>();
            Console.WriteLine(apiController._apiFileTester);
        }
    }

    public static void RegisterAutofac()
    {
        var builder = new ContainerBuilder();
        //builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
        builder.RegisterType<ApiFileTester>().As<IApiFlTester>().InstancePerLifetimeScope();
        builder.RegisterType<ApiFileSendingController>().AsSelf();
        builder.RegisterType<DTO>().AsSelf();
        _container = builder.Build();
    }

    public class ApiFileSendingController : ApiClientBase
    {
        public readonly IApiFlTester _apiFileTester;
        public ApiFileSendingController(DTO dto, IApiFlTester tester): base (dto)
        {
            _apiFileTester = tester;
        }
    }

    public interface IApiFlTester { }
    public class ApiFileTester : IApiFlTester { }
    public class ApiClientBase 
    {
        public ApiClientBase(DTO dto)
        {
        }
    }
    public class DTO { }
}

答案 1 :(得分:-1)

您对Autofac DI有误解,大多数DI框架都擅长为您创建实例,通过构造函数注入和属性注入,您将获得实例及其依赖关系自动连接的实例。 您的构造函数包含您将在运行时提供的DTO实例,由于您在ConfigureServices周期中未将其声明给DI容器,因此Autofac不会解决该问题。

在这种情况下,您可能需要放弃使用Autofac来自由地在自己的代码中创建控制器实例,而您需要从Reflection中获取具体的类实例。通过这种方法仍然可以实现抽象/实现隔离。

公共类ApiFileSendingController:ApiClientBase     {         私有只读IApiFlTester _apiFileTester;

    public ApiFileSendingController(DTO dto, IApiFlTester tester) : base(dto)
    {
       if (tester is null)
        _tester = GetApiTesterViaReflection(); 
       else
        _tester = tester;
    }

    public ApiFileSendingController(DTO dto) : base(dto)
    {
        _apiFileTester = GetApiTesterViaReflection();
    }


    public void Send(List<AftInvFileDTO> filesToSendRetry = null)
    {
        _apiFileTester.RegisterTestingMethods();
    }

    private IApiFlTester GetApiTesterViaReflection()
    {
        Type type = typeof(IApiFlTester).Assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IApiFlTester))).FirstOrDefault();
        return Activator.CreateInstance(type) as IApiFlTester;
    }

}