C#如何动态检测泛型

时间:2019-01-05 19:44:07

标签: c# reflection

我有一种方法,我喜欢使用反射机制执行一些不同的转换。

private static T GetObject<T>(Dictionary<string, object> dict)
{
    Type type = typeof(T);
    var obj = Activator.CreateInstance(type);
    foreach (var kv in dict)
    {
        var p = type.GetProperty(kv.Key);
        Type t = p.PropertyType;
        Type t2 = kv.Value.GetType();
        if (t == t2)
        {
            p.SetValue(obj, kv.Value);
        }
        else if (!IsPrimitive(p.PropertyType)) 
        {
            p.SetValue(obj, GetObject<class of p>((Dictionary<string, object>) kv.Value)); //???
        }
        else
        {
            p.SetValue(obj, (primitive)(kv.Value)); //???                    
        }
    }
    return (T)obj;
}

已编辑

我有一个字典,我想将其转换为自定义类,字典中的每个键都是一个属性,每个字典值都是该属性的值。问题出现在两种情况下,当类属性类型和字典值类型都是原始类型,但它们具有不同的类型(例如,属性为int但字典值很长)时,第二个问题出现在当属性值是另一个自定义类并且在这种情况下,词典值始终是另一本词典

如何动态检测必要的演员表/广播?

2 个答案:

答案 0 :(得分:2)

首先查看类型是否与分配兼容

if (t.IsAssignableFrom(t2))

否则用

进行转换
object converted = Convert.ChangeType(kv.Value, t);

这应该处理很多情况。

由于必须使用仅在运行时才知道的类型来递归调用该方法,因此最好使用GetObject的非泛型重载版本。原始方法仅调用非通用方法

private static T GetObject<T>(Dictionary<string, object> dict)
    where T : class, new() // Suggested by Brett Caswell.
{
    return (T)GetObject(dict, typeof(T));
}

请注意,泛型类型参数始终在编译时解析。由于您必须在运行时动态解析类型,因此在这里它们更是一个障碍。您可以使用反射来构造泛型方法调用,但这样做没有任何好处。它很复杂,类型也不安全。类型安全只能由编译器强制执行。

private static object GetObject(Dictionary<string, object> dict, Type objectType)
{
    object obj = Activator.CreateInstance(objectType);
    foreach (var kv in dict) {
        PropertyInfo prop = objectType.GetProperty(kv.Key);
        Type propType = prop.PropertyType;
        object value = kv.Value;
        if (value == null) {
            if (propType.IsValueType) { // Get default value of type.
                value = Activator.CreateInstance(propType);
            }
        } else if (value is Dictionary<string, object> nestedDict) {
            value = GetObject(nestedDict, propType);
        } else if (!propType.IsAssignableFrom(value.GetType())) {
            value = Convert.ChangeType(value, propType);
        }
        prop.SetValue(obj, value);
    }
    return obj;
}

答案 1 :(得分:-1)

此问题的更好解决方法是应用uncle Bob's S.O.L.I.D原理之一,即开闭原理。这是该原理的经典示例

public abstract class Shape
{
        public abstract double Area();
 } 

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }
    public override double Area()
    {
        return Width*Height;
    }
}

public class Circle : Shape
{
    public double Radius { get; set; }
    public override double Area()
    {
        return Radius*Radius*Math.PI;
    }
} 

通过这种方式,您不必制作if树,而是要实现抽象类,则每次将其与任何Class一起使用时,都必须实现Area方法。希望达到目的