问题
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