首页 > 解决方案 > 检查对象是否为字典或字典联合类型

问题描述

我有一个功能

public static async void MyFunction(object Obj)
{
    if (Obj.GetType() == typeof(Dictionary<string, string>))
    {
        // My Code
    }
}

我想检查参数Obj 是否为类型Dictionary<string, string>Dictionary<string, string>.Union(Dictionary<string, string>).

如果传递给函数的对象是字典类型字典联合||类型,我应该在上面的语句中添加什么条件if以便执行块?if

我该怎么做?

标签: c#dictionarytypeofgeneric-collections

解决方案


使用扩展方法:

public static bool IsAssignableToGenericType(this Type givenType, Type genericType) {
    if (givenType.IsGenericType && givenType.IsGenericEqual(genericType))
        return true;

    if (givenType.GetInterface(genericType.Name) != null)
        return true;

    foreach (var it in givenType.GetInterfaces())
        if (it.IsAssignableToGenericType(genericType))
            return true;

    var baseType = givenType.BaseType;
    if (baseType == null)
        return false;

    return baseType.IsAssignableToGenericType(genericType);
}

你可以测试:

if (Obj.GetType().IsAssignableToGenericType(typeof(IEnumerable<KeyValuePair<string,string>>))) {

这不保证Obj是调用的产物Union。如果你需要这样做,你需要深入研究类型。

使用一些扩展方法使反射更容易:

public static class ObjectExt {
    public static object GetPrivateValue<T>(this T obj, string memberName) =>
        obj.GetType().GetPropertyOrField(memberName, BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public).GetValue(obj);
}

public static class TypeExt {
    public static MemberInfo GetPropertyOrField(this Type t, string memberName, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
        t.GetMember(memberName, bf).Where(mi => mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property).Single();
}

public static class MemberInfoExt {
    public static object GetValue(this MemberInfo member, object srcObject) {
        switch (member) {
            case FieldInfo mfi:
                return mfi.GetValue(srcObject);
            case PropertyInfo mpi:
                return mpi.GetValue(srcObject);
            case MethodInfo mi:
                return mi.Invoke(srcObject, null);
            default:
                throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or MethodInfo", nameof(member));
        }
    }
}

您可以确定该对象来自a UnionDictionary请注意,这取决于 .Net Core 的内部结构,将来可能无法使用:

var isDictUnion = (Obj.GetType() == unionType) && (Obj.GetPrivateValue("_first").GetType() == dictType) && (Obj.GetPrivateValue("_second").GetType() == dictType);

推荐阅读