在运行时创建属性的未知类类型的实例

本文关键字:类型 实例 未知 创建 属性 运行时 | 更新日期: 2023-09-27 18:31:17

我需要检测属性的类型何时是类类型及其构造函数参数(如果有)。类会有所不同,并且不能硬编码。我有一个如下所示的属性类型,并且使用反射,我根据确定的类型以不同的方式处理属性。

public class SomeClass
{
    // Process this one and instantiate its class type
    public WhateverClass Whatever
    {
        get;
        set;
    }
    // This one will be skipped since its not a user defined class type
    public string SomePropName
    {
        get;
        set;
    }
}

现在,当我反映类中的属性时(例如 SomeClass)。我需要对属性类型做一些不同的事情,但有些类型是类,它们在构造函数中可能有也可能不需要参数,但由于它在运行时全部确定,我必须动态反映构造函数。

if (propertyInfo.PropertyType.IsClass)
{
    var propType = propertyInfo.PropertyType.UnderlyingSystemType;
    // Something like this
    var ctx = propType.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, null, null);
    // todo: instanciate new class instance
}

现在有没有更好的方法来剥这只猫的皮,如果没有,当我不知道构造函数参数时,我该如何创建类?

谢谢

在运行时创建属性的未知类类型的实例

如果你需要知道一个对象的任何/所有构造函数,有一个" GetConstructors"方法返回该类的构造函数数组:

propType.GetConstructors();

前任:

public class PropertyClass
{
    public PropertyClass()
    {
        Value = "default";
    }
    public PropertyClass(string value)
    {
        Value = value;
    }
    public string Value { get; private set; }
}
public class WhateverClass
{
    public PropertyClass Property { get; set; }   
}

用法

var propertyInstances = GeneratePropertyForEachConstructor(typeof(WhateverClass), "Property").Cast<PropertyClass>();
foreach (PropertyClass propertyInstance in propertyInstances)
{
    Console.WriteLine("value: {0}", propertyInstance.Value);
}

方法:

public List<object> GeneratePropertyForEachConstructor(Type type, string propertyName)
{
    var propertyInfo = type.GetProperty(propertyName);
    return GeneratePropertyForEachConstructor(type, propertyInfo);
}
public List<object> GeneratePropertyForEachConstructor(Type type, PropertyInfo propertyInfo)
{
    List<object> results = new List<object>();
    if (propertyInfo.PropertyType.IsClass)
    {
        var propType = propertyInfo.PropertyType.UnderlyingSystemType;
        var constructors = propType.GetConstructors();
        foreach (ConstructorInfo constructorInfo in constructors)
        {
            var parameterInfo = constructorInfo.GetParameters();
            var constructorParams = new List<object>();
            foreach (ParameterInfo constructorParam in parameterInfo)
            {
                object value = constructorParam.HasDefaultValue
                                   ? constructorParam.DefaultValue
                                   : constructorParam.ParameterType.IsValueType
                                         ? Activator.CreateInstance(constructorParam.ParameterType)
                                         : null;
                constructorParams.Add(value);
            }
            results.Add(constructorInfo.Invoke(constructorParams.ToArray()));
        }
    }
    return results;
} 

输出

值:默认值

价值:

在这种情况下,我们可以看到它遍历了两个构造函数,并为具有 String 参数的构造函数传入了 String 的默认值。