Use Activator.CreateInstance() and support multiple constructor signatures

烈酒焚心 提交于 2021-02-11 18:22:59

问题


I need to instantiate a type that MUST have a IConfiguration parameter, but MAY have other parameters.

Currently I use the following code:

Activator.CreateInstance(myType, BindingFlags.CreateInstance, null, new object[] { configuration }, CultureInfo.InvariantCulture);

myType is the type to instantiate. Written like this, it requires a constructor that has exactly one parameter of type IConfiguration. As you can see, I pass the configuration object via object array to satisfy this requirement.

Now there is a new requirement: The constructor of myType can have multiple parameters. One of them has to accept an IConfiguration object. The other parameters can be ignored (or set to default) in this part of the code. How can I achieve this?

Edit:

These are possible types for myType. V1 is the current requirement, V2 is the new requirement. All three variants are valid and need to be instantiated with a configuration object.

public class PluginV1
{
    private readonly IConfiguration configuration;

    public PluginV1(IConfiguration configuration)
    {
        this.configuration = configuration;
    }
}

public class PluginV2_A
{
    private readonly IConfiguration configuration;
    private readonly IExampleService exampleService;

    public PluginV2_A(IConfiguration configuration, IExampleService exampleService)
    {
        this.configuration = configuration;
        this.exampleService = exampleService;
    }
}

public class PluginV2_B
{
    private readonly IConfiguration configuration;
    private readonly IEnvironment environment;

    public PluginV2_B(IConfiguration configuration, IEnvironment environment)
    {
        this.configuration = configuration;
        this.environment = environment;
    }
}

回答1:


Maybe I'm missing something, but you can use simple reflection to get right constructor, in case there are more than one, and explore its input parameters.

    public class Config : IConfiguration{}

    static void Main(string[] args)
    {
        var config = new Config();

        var o1  = Instantiate(typeof(PluginV1), config);
        var o2  = Instantiate(typeof(PluginV2_A), config);
        var o3  = Instantiate(typeof(PluginV2_B), config);
        Console.WriteLine(o1);
        Console.WriteLine(o2);
        Console.WriteLine(o3);
        Console.ReadKey();
    }

    private static object? Instantiate(Type type, IConfiguration config)
    {
        var targetConstructor =  type.GetConstructors().First();
        // in case there are several .ctors we can find suitable
        //        .First(info => info.GetParameters().Any(parameterInfo =>
        //            typeof(IConfiguration).IsAssignableFrom(parameterInfo.ParameterType)));
        var parameters = targetConstructor.GetParameters().Select(info =>
        {
            if (!typeof(IConfiguration).IsAssignableFrom(info.ParameterType))
            {
                return GetDefault(info.ParameterType);
            }

            return config;
        }).ToArray();
        var instance = Activator.CreateInstance(type, parameters);
        return instance;
    }

    // getting default values https://stackoverflow.com/a/353073/517446
    public static object GetDefault(Type type)
    {
        if(type.IsValueType)
        {
            return Activator.CreateInstance(type);
        }
        return null;
    }


来源:https://stackoverflow.com/questions/60511192/use-activator-createinstance-and-support-multiple-constructor-signatures

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!