I have a class with a bunch of properties of type ISet<T>
, where T varies from property to property.
I'd like to iterate over an object's properties, find the ones that are some sort of ISet
and call Count on each of them.
Thanks.
I have a class with a bunch of properties of type ISet<T>
, where T varies from property to property.
I'd like to iterate over an object's properties, find the ones that are some sort of ISet
and call Count on each of them.
Thanks.
This might work, obj
is a target object:
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's answer worked for me, but I tweaked it into something I found more convenient:
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;
}
Also, I found that if I can refer to the properties by name I can use
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}" : "";
}
as in
$"{count(x => x.prop)}"