Конфигурация динамического связывания Mvc Core

Мне интересно, можно ли динамически привязать раздел конфигурации к объекту. Обычно для привязки раздела конфигурации мы пишем такой код:

var section = Configuration.GetSection(nameof(MyCustomSection));
services.Configure<MyCustomSection>(o => secto.Bind(o));

Мне интересно, можно ли это сделать без объявления типа <MyCustomSection>.

//This doesn't work, just trying to show you how I would like to do it
services.Configure(MyType, o => section.Bind(o));

Например, если я хочу привязать инъекцию, я могу сделать это так:

services.AddTransient<IDateTime, SystemDateTime>();

Но я также могу сделать это динамически, например:

services.AddTransient(Type1, Type2));

Возможно ли то же самое для services.Configure? Я посмотрел на параметры метода, но, похоже, он его не поддерживает. Просто интересно, есть ли другой способ, или, может быть, я просто что-то упускаю из виду?

Обновлено:

services.AddSingleton(p =>   
{
    var type = new MySection();
    Configuration.GetSection("MySection").Bind(type);
    return type;
});

Затем я вызываю это в таком классе:

public class Test {
    public Test(IOptions<MySection> section)
    {
        var finalValue = section.Value;
    }
}

finalValue всегда равен нулю;

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
570
2

Ответы 2

Во-первых, все, что делает Configure, это

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

Следовательно, если у Configure нет перегрузки для выполнения того, что вы хотите, вы можете просто перейти к отдельным задачам, т.е.

services.AddSingleton(p =>
{
    var config = Activator.CreateInstance(type);
    Configuration.GetSection("Foo").Bind(config);
    return config;
}

Я пробовал следовать вашему примеру, и он всегда дает мне нулевое значение. Я обновил свой вопрос кодом, который я пробовал на основе вашего примера. Вы знаете, не упустил ли я что-нибудь?

Bagzli 25.06.2018 20:34

Я предполагаю, что это какая-то проблема с тем, как вы получаете SectionName, т.е. он, вероятно, возвращает null или что-то в этом роде, так что на самом деле не удается найти раздел для привязки. FWIW, я тестировал этот код в своем собственном проекте и могу подтвердить, что он работает.

Chris Pratt 25.06.2018 21:24

Проблема в том, что я пытался вызвать IOptions <MyType>, а не только MyType. Это решение в конечном итоге дает мне динамическое связывание, но оно больше не проходит через IOptions.

Bagzli 25.06.2018 22:39

В любом случае вам не нужен IOptions. Единственная ценность - в IOptionsSnapshot, но я, к сожалению, не смог найти способ заставить это работать. Таким образом, вы не получите перезагрузку с помощью этого метода, но в зависимости от вашего приложения это может не иметь значения.

Chris Pratt 26.06.2018 00:27

Если вы действительно этого хотите, вы можете использовать отражение для вызова services.Configure<TOptions>() с аргументом динамического универсального типа во время выполнения. Однако может быть более простой способ получить желаемый результат (используя IOptions<>), используя некоторую модификацию ответа Криса.

Используйте это так:

services.Configure(MyType, o => { var castObj = (MyType)o; section.Bind(castObj); });


using System;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;

namespace WebApplication1
{
    public static class MyServiceExtensions
    {
        public static IServiceCollection Configure(this IServiceCollection services, Type type, Action<object> configureOptions)
        {
            // Static type that contains the extension method
            var extMethodType = typeof(OptionsServiceCollectionExtensions);

            // Find the overload for Configure<TOptions>(IServiceCollection, Action<TOptions>)
            // This could be more specific to make sure that all type arguments are exactly correct.
            // As it stands, this returns the correct overload but future updates to OptionsServiceCollectionExtensions
            // may add additional overloads which will require this to be updated.
            var genericConfigureMethodInfo = extMethodType.GetMethods()
                .Where(m => m.IsGenericMethod && m.Name == "Configure")
                .Select(m => new
                {
                    Method = m,
                    Params = m.GetParameters(),
                    Args = m.GetGenericArguments() // Generic Type[] (ex [TOptions])
                })
                .Where(m => m.Args.Length == 1 && m.Params.Length == 2
                    && m.Params[0].ParameterType == typeof(IServiceCollection))
                .Select(m => m.Method)
                .Single();

            var method = genericConfigureMethodInfo.MakeGenericMethod(type);

            // Invoke the method via reflection with our converted Action<objct> delegate
            // Since this is an extension method, it is static and services is passed
            // as the first parameter instead of the target object
            method.Invoke(null, new object[] { services, configureOptions });

            return services;
        }
    }
}

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

Bagzli 25.06.2018 22:57

Вы можете найти более чистый способ внедрить настроенные параметры через IOptions, если вы посмотрели на реализацию .Configure<>() с открытым исходным кодом, но это решение должно работать нормально. Я не проводил никаких тестов с наследованием типов, поэтому может быть что-то упущено из виду

Neil 25.06.2018 23:03

Другие вопросы по теме