C# 反射-使用参数调用构造函数
我从加载的程序集中读取类型,例如:C# 反射-使用参数调用构造函数,c#,reflection,enums,C#,Reflection,Enums,我从加载的程序集中读取类型,例如: var someType = loadedAssemblies .Where(a => a != null && a.FullName.StartsWith("MY.")) .SelectMany(a => a.GetTypes()) .Distinct() .ToArray()[0]; 如果Constructor有参数,我可以读取它们
var someType = loadedAssemblies
.Where(a => a != null && a.FullName.StartsWith("MY."))
.SelectMany(a => a.GetTypes())
.Distinct()
.ToArray()[0];
如果Constructor有参数,我可以读取它们:
ParameterInfo[] parameters = classType.GetConstructors()[0].GetParameters();
我希望使用默认参数值调用构造函数,或者如果参数是enum,则使用第一个enum值调用构造函数。
如果只有一个参数且为enum,则其工作原理如下:
object curObject = Activator.CreateInstance(classType, new object[] { parameters[0].ParameterType.GetEnumValues().GetValue(0) });
var parameters = constructor
.GetParameters()
.Select(p => p.HasDefaultValue ? p.RawDefaultValue : GetDefaultValue(p.ParameterType))
.ToArray();
当有更多参数时,如何执行此操作?
我需要创建对象来读取属性:
var propertyInfo = someType.GetProperty("EntityType");
string entityType = propertyInfo.GetValue(curObject, null).ToString();
您可以创建一个助手方法来获取类型的默认值:
private static object GetDefaultValue(Type type)
{
if (type.IsEnum) return type.GetEnumValues().GetValue(0);
if (type.IsValueType) return Activator.CreateInstance(type);
return null;
}
然后,您可以获得参数的默认值:
var parameters = constructor.GetParameters()
.Select(p => GetDefaultValue(p.ParameterType))
.ToArray();
并调用ConstructorInfo
以获取实例:
var obj = constructor.Invoke(parameters);
如果构造函数的参数具有默认值,并且您希望使用它们,则可以执行以下操作:
object curObject = Activator.CreateInstance(classType, new object[] { parameters[0].ParameterType.GetEnumValues().GetValue(0) });
var parameters = constructor
.GetParameters()
.Select(p => p.HasDefaultValue ? p.RawDefaultValue : GetDefaultValue(p.ParameterType))
.ToArray();
您可以创建自己的工厂,并编写一个方法,用于检查构造函数的类型,并使用默认值运行第一个参数化的构造函数:
public static class MyFactory
{
public static T MyCreateInstance<T>()
where T : class
{
return (T) MyCreateInstance(typeof (T));
}
public static object MyCreateInstance(Type type)
{
var parametrizedCtor = type
.GetConstructors()
.FirstOrDefault(c => c.GetParameters().Length > 0);
return parametrizedCtor != null
? parametrizedCtor.Invoke
(parametrizedCtor.GetParameters()
.Select(p =>
p.HasDefaultValue? p.DefaultValue :
p.ParameterType.IsValueType && Nullable.GetUnderlyingType(p.ParameterType) == null
? Activator.CreateInstance(p.ParameterType)
: null
).ToArray()
)
: Activator.CreateInstance(type);
}
}
附言。
这是一本书
更新:
代码会根据您使用的场景进行更改。现在我们有两种方法,
一个返回对象,另一个可以将其转换为T类型
我还更新了DotnetFiddle,请检查。你好,Fabjan,感谢您提供此解决方案。有一个问题。我只有在运行时读取的类类型。我不知道编译时的对象(类)名称。您的代码:var curObject=MyFactory.MyCreateInstance(类类型);不适用于object关键字。我已经在DotNetFiddle上更新了我的答案和代码示例。谢谢,它工作得很好。你知道constructor.Invoke和Activator.CreateInstance的区别吗?Arturo,constructor.Invoke和Activator.CreateInstance的区别是什么?你能用Activator.CreateInstance做同样的事情吗?@Simon:
Constructor.Invoke
直接调用该构造函数Activator.CreateInstance
创建一个实例,查找与指定参数最匹配的构造函数。