title: Retrieve Properties of HashSet passed as Object
body: <p>I'm maintaining part of an application which takes an entity framework entity as an object and returns a list of all its properties and corresponding values.</p>
  
  <p>The method looks something like this:</p>
  
  <pre><code>public static List&lt;string&gt; ExtractAttributes(object data)
  {
      List&lt;string&gt; attributes = new List&lt;string&gt;();
  
      foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(data))
      {
          Console.WriteLine("Name: {0}  Value: {1}  Type: {2}", property.Name, property.GetValue(data), data.GetType());
  
          attributes.Add(property.Name);
      }
      return attributes;
  }
  </code></pre>
  
  <p>On calling this method with the following object:</p>
  
  <pre><code>ExtractAttributes(HashSet&lt;Dog&gt; dogs);
  </code></pre>
  
  <p>The method returns Count and Comparer (properties of HashSet) rather than properties of Dog. Therefore it is necessary to convert the <code>data</code> object to the first object of the hashset collection (it only needs to be the first object in the set for reasons too long to explain in detail).</p>
  
  <p>The code I've written to do this is as follows:</p>
  
  <pre><code>public static List&lt;String&gt; ExtractAttributes(object data)
  {
  ...
  if (data.GetType().IsGenericType &amp;&amp;
      data.GetType().GetGenericTypeDefinition() == typeof(HashSet&lt;&gt;))
  {
      List&lt;object&gt; hashSetAsList = new List&lt;object&gt;((IEnumerable&lt;object&gt;)data);
      if (hashSetAsList.Count &gt; 0)
      {
          data = hashSetAsList[0];
      }
  }
  ...
  }
  </code></pre>
  
  <p>Is there any way to improve this ugly-looking code given the constraint of being unable to alter anything else in the method/return type?</p>
  
  <p><strong>Edit</strong>
  The ExtractAttributes method is recursive (in a way which depends on the logic of some external XML) but can be represented as:</p>
  
  <pre><code>foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(data))
  {
      Console.WriteLine("Name: {0}  Value: {1}  Type: {2}", property.Name, property.GetValue(data), data.GetType());
  
      if (property.GetValue(data).GetType().IsGenericType)
      {
          attributes.AddRange(ExtractAttributes(property.GetValue(data)));
      }
  }
  </code></pre>