Как разрешить интерфейс и использовать его в классе с помощью Autofac - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь разрешить интерфейс, который я зарегистрировал в Autofac, но он, похоже, не работает.Существует исключение нулевой ссылки.

Класс, в котором я регистрирую интерфейс:

    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 sender = новый ApiFileSendingController (dto, null);

, но это ноль и это вполне разумно (я передаюноль).Можно ли настроить необязательный параметр или что-то еще?Я хотел бы, чтобы этот интерфейс разрешался автоматически с помощью функции автозапуска, а не вручную.

Ответы [ 2 ]

0 голосов
/ 14 мая 2019

У меня, похоже, нет проблем с решением вашего класса. Технически невозможно действительно ответить на ваш вопрос, так как код даже не скомпилируется, и кажется, что у вас тонна пропущенных регистраций автофака.

Рабочий пример .

// @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 { }
}
0 голосов
/ 14 мая 2019

У вас неправильное представление в Autofac DI, большинство структур DI хорошо умеют создавать экземпляры для вас, с помощью внедрения конструктора и свойства вы получите экземпляр с автоматически подключенными зависимостями.Ваш конструктор содержит экземпляр DTO, который вы предоставите во время выполнения, Autofac не разрешит это, поскольку вы не объявляли его контейнеру DI во время цикла ConfigureServices.

В этом случае вам может потребоваться отказаться от использования Autofac, чтобы получитьсвобода создания экземпляра контроллера в вашем собственном коде, вам нужно будет получить конкретный экземпляр класса из Reflection.Благодаря этому подходу абстракция / реализация все еще существует.

открытый класс ApiFileSendingController: ApiClientBase {private readonly 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;
    }

}
...