Reputation: 351
I tried to find out all the "string" type properties from a class, but wonder how can I do that if there is any class type property in this class.
The following codes show the target class and my solution.
public class Credit_Card
{
public string brand { get; set; }
public string billing_phone { get; set; }
public Expiration expiration { get; set; }
}
public class Expiration
{
public string month { get; set; }
}
class program
{
static void Main(string[] args)
{
foreach (PropertyInfo prop in typeof(Credit_Card).GetProperties())
{
if(prop.PropertyType == typeof(string))
{
Console.WriteLine(prop.Name);
}
}
Console.ReadLine();
}
}
My "Main" method can only show "brand" and "billing_phone" properties in Credit_Card type, but missed "month" property in expiration class.
Is there any way that I can do recursive search in Credit_Card class?
Upvotes: 0
Views: 119
Reputation: 113272
public static void Main (string[] args)
{
foreach(PropertyInfo prop in GetStringProperties(typeof(Credit_Card)))
Console.WriteLine(prop.Name);
Console.ReadLine();
}
public static IEnumerable<PropertyInfo> GetStringProperties(Type type)
{
return GetStringProperties (type, new HashSet<Type> ());
}
public static IEnumerable<PropertyInfo> GetStringProperties(Type type, HashSet<Type> alreadySeen)
{
foreach(var prop in type.GetProperties())
{
var propType = prop.PropertyType;
if (propType == typeof(string))
yield return prop;
else if(alreadySeen.Add(propType))
foreach(var indirectProp in GetStringProperties(propType, alreadySeen))
yield return indirectProp;
}
}
It's important to catch types we've already processed, or you can easily get into an infinite loop with the small mercy that since this takes a recursive approach it crashes with a StackOverflowException
rather than just hanging forever like the iterative equivalent would. (Another case of the only thing worse than throwing an exception is no throwing an exception).
Upvotes: 0
Reputation: 156524
You should be able to make a method that will recursively call itself, with the type to search as a parameter:
public void OutputStringProperties(Type type)
{
foreach (PropertyInfo prop in type.GetProperties())
{
if(prop.PropertyType == typeof(string))
{
Console.WriteLine(prop.Name);
}
else
{
OutputStringProperties(prop.PropertyType);
}
}
}
Then your initial call just invokes this with its starting point:
OutputStringProperties(typeof(Credit_Card));
However, bear in mind that this will cause a stack overflow if you have cyclic dependencies, unless you first modify it to keep track of which types it's already checked.
Upvotes: 1