反思 - 调用构造函数参数
我从加载的程序集读取类型,例如:反思 - 调用构造函数参数
var someType = loadedAssemblies
.Where(a => a != null && a.FullName.StartsWith("MY."))
.SelectMany(a => a.GetTypes())
.Distinct()
.ToArray()[0];
如果counstructor有参数,我能读懂他们:
ParameterInfo[] parameters = classType.GetConstructors()[0].GetParameters();
我想调用默认的构造函数参数值或者如果参数是枚举,则使用第一个枚举值。 如果只有一个参数,它是枚举,它的工作原理是这样的:
object curObject = Activator.CreateInstance(classType, new object[] { parameters[0].ParameterType.GetEnumValues().GetValue(0) });
我怎么能做到这一点的时候有更多的参数呢? 我需要创建对象读取属性:
var propertyInfo = someType.GetProperty("EntityType");
string entityType = propertyInfo.GetValue(curObject, null).ToString();
好了,你可以创建自己的工厂,并编写方法,即检查类的构造函数使用默认参数:
public static class MyFactory
{
public static T MyCreateInstance<T>()
where T : class
{
return (T) MyCreateInstance(typeof (T));
}
public static object MyCreateInstance(Type type)
{
var ctor = type
.GetConstructors()
.FirstOrDefault(c => c.GetParameters().Length > 0);
return ctor != null
? ctor.Invoke
(ctor.GetParameters()
.Select(p =>
p.HasDefaultValue? p.DefaultValue :
p.ParameterType.IsValueType && Nullable.GetUnderlyingType(p.ParameterType) == null
? Activator.CreateInstance(p.ParameterType)
: null
).ToArray()
)
: Activator.CreateInstance(type);
}
}
然后你就可以用这个方法:
var classType = loadedAssemblies
.Where(a => a != null && a.FullName.StartsWith("MY."))
.SelectMany(a => a.GetTypes())
.Distinct()
.ToArray()[0];
var curObject = MyFactory.MyCreateInstance(classType);
// This will return an array of values
object[] values = classType
.GetFields()
.Select(f => f.GetValue(curObject))
.ToArray();
P.S. 这是DotNet fiddle example。
更新:
的代码是根据你一起工作的场景改变。现在我们有两种方法,一种返回对象 ,另一种可以将其转换为T型。
我也更新了DotnetFiddle,请检查它。
你可以做一个辅助方法来获得一个类型的默认值:
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);
如果构造函数的参数有默认值,你要使用它们,你可以做这样的事情:
var parameters = constructor
.GetParameters()
.Select(p => p.HasDefaultValue ? p.RawDefaultValue : GetDefaultValue(p.ParameterType))
.ToArray();
Arturo,constructor.Invoke与Activator.CreateInstance有什么区别?你可以用Activator.CreateInstance做同样的事吗? – Simon
@Simon:'Constructor.Invoke'直接调用该构造函数。 'Activator.CreateInstance'创建一个实例,查找与指定参数最匹配的构造函数。 –
嗨,Fabjan,谢谢你的解决方案。有一个问题。 我只有classType,我在运行时读取。我不知道在编译时的对象(类)名称。你的代码:var curObject = MyFactory.MyCreateInstance
我已经更新了我的答案以及DotNetfiddle上的代码示例 – Fabjan
谢谢,它完美无缺。你知道constructor.Invoke与Activator.CreateInstance之间的区别吗? – Simon