Mvc Core Конфигурация динамического связывания - PullRequest
0 голосов
/ 25 июня 2018

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

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 всегда равно нулю;

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Если вы действительно хотите, вы можете использовать рефлексию для вызова 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;
        }
    }
}
0 голосов
/ 25 июня 2018

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

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

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

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