如何在 T 变化的一堆 ISet<T> 属性上调用 Count

How to call Count on a bunch of ISet<T> properties where T varies

我有一个 class,它有一堆 ISet<T> 类型的属性,其中 T 从 属性 到 属性。

我想遍历一个对象的属性,找到某种 ISet 的属性,然后对每个属性调用 Count。

谢谢。

这可能有效,obj 是一个目标对象:

Type targetType = obj.GetType();
foreach (var propertyInfo in targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy))
{
    var isetInterface = propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ISet<>)
        ? propertyInfo.PropertyType
        : null;

    if(isetInterface == null)
    {
        isetInterface = propertyInfo.PropertyType
            .GetInterfaces()
            .FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ISet<>));
    }

    if (isetInterface != null)
    {
        object isetPropertyValue = propertyInfo.GetValue(obj);

        var countPropertyInfo = isetInterface
            .GetInterfaces()
            .First(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ICollection<>))
            .GetProperty("Count");

        if (isetPropertyValue == null)
        {
            Console.WriteLine($".{propertyInfo.Name} == null");
        }
        else
        {
            var count = countPropertyInfo.GetValue(isetPropertyValue);
            Console.WriteLine($".{propertyInfo.Name}.Count == {count}");
        }
    }
}

@Renat 的回答对我有用,但我将其调整为我觉得更方便的内容:

        public virtual string counts => typeof(Changeset)
        .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)
        .Where(prop => prop.GetValue(this) != null && count(prop) > 0)
        .Select(prop => $@".{prop.Name}.Count == {count(prop)}")
        .Join("\n");

    private int count(PropertyInfo prop)
    {
        var name = prop.Name;
        var isetInterface = prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(ISet<>)
            ? prop.PropertyType
            : null;

        if (isetInterface == null)
        {
            isetInterface = prop.PropertyType
                .GetInterfaces()
                .FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ISet<>));
        }

        if (isetInterface != null)
        {
            object isetPropertyValue = prop.GetValue(this);

            var countPropertyInfo = isetInterface
                .GetInterfaces()
                .First(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ICollection<>))
                .GetProperty("Count");

            if (isetPropertyValue == null)
                return 0;
            else
                return (int) countPropertyInfo.GetValue(isetPropertyValue);
        }

        return 0;
    }

此外,我发现如果我可以按名称引用属性,我就可以使用

    private string count<T>(Func<Changeset, ISet<T>> selector)
    {
        var count = selector(this).Count;
        return count > 0 ? $"\n{typeof(T).Name}s:\t\t{count}" : "";
    }

$"{count(x => x.prop)}"