Nano Hash - криптовалюты, майнинг, программирование

Как зарегистрировать делегата или функцию в Autofac, если функция принадлежит классу, который необходимо разрешить?

Я использую Автофак. Я хочу ввести делегата в класс:

public delegate ValidationResult ValidateAddressFunction(Address address);

public class OrderSubmitHandler
{
    private readonly ValidateAddressFunction _validateAddress;

    public OrderSubmitHandler(ValidateAddressFunction validateAddress)
    {
        _validateAddress = validateAddress;
    }

    public void SubmitOrder(Order order)
    {
        var addressValidation = _validateAddress(order.ShippingAddress);
        if(!addressValidation.IsValid)
            throw new Exception("Your address is invalid!");
    }
}

Реализация ValidateAddressFunction, которую я хочу внедрить, исходит из класса, который должен быть разрешен из контейнера, поскольку у него есть собственные зависимости:

public class OrderValidator
{
    private readonly ISomeDependency _dependency;

    public OrderValidator(ISomeDependency dependency)
    {
        _dependency = dependency;
    }

    public ValidationResult ValidateAddress(Address address)
    {
        // use _dependency
        // validate the order
        // return a result
        return new ValidationResult();
    }
}

В этом примере я использую делегат, но с тем же успехом я мог бы внедрить Func<Address, ValidationResult>.

Я мог бы просто внедрить OrderValidator, но я бы не стал создавать интерфейс только с одним методом. Если все, что нужно моему классу, - это один метод, то я бы предпочел напрямую зависеть от него.

Как зарегистрировать делегат или Func таким образом, чтобы при его разрешении класс, содержащий метод, был разрешен, а затем я мог использовать метод из разрешенного экземпляра?


Ответы:


1

Зарегистрируйте делегат или Func<Address, ValidationResult>, используя фабричный метод, который разрешает тип, предоставляющий метод, а затем возвращает метод.

В вашем примере вы хотели бы разрешить OrderValidator и вернуть его метод ValidateAddress.

var builder = new ContainerBuilder();

// register the class that provides the method and its dependencies.

builder.RegisterType<OrderValidator>();
builder.RegisterType<SomeDependency>().As<ISomeDependency>();

// register the delegate using a factory method that resolves 
// the type that provides the method and then returns the method.

builder.Register<ValidateAddressFunction>(context =>
{
    var validator = context.Resolve<OrderValidator>();
    return validator.ValidateAddress;
});

Это будет работать точно так же, если вы регистрируете Func<Address, ValidationResult> вместо делегата:

builder.Register<Func<Address, ValidationResult>>(context =>
{
    var validator = context.Resolve<OrderValidator>();
    return validator.ValidateAddress;
});

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

public static class AutofacDelegateExtensions
{
    public static IRegistrationBuilder<TDelegate, SimpleActivatorData, SingleRegistrationStyle> RegisterDelegateFromService<TService, TDelegate>(
        this ContainerBuilder builder,
        Func<TService, TDelegate> getDelegateFromService,
        string sourceComponentName = null)
        where TDelegate : class
    {
        var registrationFunction = new Func<IComponentContext, TDelegate>(context =>
        {
            var source = sourceComponentName == null
                ? context.Resolve<TService>()
                : context.ResolveNamed<TService>(sourceComponentName);
            return getDelegateFromService(source);
        });

        return builder.Register(registrationFunction);
    }
}

Регистрация Autofac по умолчанию является временной, поэтому время жизни класса, предоставляющего делегата, определяется регистрацией этого класса.

Теперь регистрация будет выглядеть так:

builder.RegisterDelegateFromService<OrderValidator, ValidateAddressFunction>(validator =>
    validator.ValidateAddress);

Или, если зависимость, которая предоставляет метод - в этом случае OrderValidator зарегистрирована с именем, и мы должны разрешить его, используя это имя:

builder.RegisterDelegateFromService<OrderValidator, ValidateAddressFunction>(validator =>
    validator.ValidateAddress, "RegistrationName");
06.06.2019
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..