title: Generics inheritance problem using reflection
body: <p>here is my problem:
  I am modifying a framework developed in my company, and we have a function that returns any changes in a class' properties.
  This is the structure in the framework:</p>
  
  <pre><code>namespace Fwk.Business.Entities
  
      public class BusinessEntity : IIdentifiable, ICloneableExt
      {
         ...
      }
  
      public class EntityList&lt;BE&gt; where BE : BusinessEntity, new()
      {
         ...
      }
  }
  </code></pre>
  
  <p>and this is a tipical use:</p>
  
  <pre><code>namespace Common.Business.Entities
  {
  
      public class ImportFileEntity : Fwk.Business.Entities.BusinessEntity
      {
         ...
      }
  
      public class ImportFileList : Fwk.Business.Entities.EntityList&lt;ImportFileEntity&gt;
      {
      }
  
  }
  </code></pre>
  
  <p>Fwk.Business.Entities.BusinessEntity has a function named GetChanges() that using reflection iterates through all properties and checks if they changed their value (using a copy of the original BusinessEntity). It even checks if the property is itself an instance of Fwk.Business.Entities.BusinessEntity and if so recursively calls the GetChanges method. But my problem is when I have a property that is an instance of Fwk.Business.Entities.EntityList. I want to call each element's GetChanges method, but I can't seem to identify these EntityList&lt;> properties.
  I've tried with </p>
  
  <pre><code>pi.GetValue(this, null).GetType().IsSubclassOf(typeof(EntityList&lt;BusinessEntity&gt;))
  </code></pre>
  
  <p>where pi is a PropertyInfo element that identifies the property I'm checking, but this returns false. I've also tried many other Type functions such as IsInstanceOfType and IsAssignableFrom, always getting a false where I need a true.
  The weird thing is that if I check for a specific BusinessEntity type it does work:</p>
  
  <pre><code>pi.GetValue(this, null).GetType().IsSubclassOf(typeof(EntityList&lt;ImportFileEntity&gt;))
  </code></pre>
  
  <p>but of course this is not acceptable since I can have a list of ANY BusinessEntity.</p>
  
  <p>Can anyone help me solve this?</p>
  
  <p>Than's in advance for all replys
  Alex.</p>
  
  <p>UPDATE:
  SLaks gave me a good answer and I coded this:</p>
  
  <pre><code>bool isEntityList = false;
  Type thisType = (pi.GetValue(this, null) ?? new object()).GetType();
  while (thisType != typeof(object) &amp;&amp; !isEntityList)
      if (thisType.IsGenericType &amp;&amp; thisType.GetGenericTypeDefinition() == typeof(EntityList&lt;&gt;))
          isEntityList = true;
      else
          thisType = thisType.BaseType;
  
  // If property is a subclass of EntityList, invoke GetChanges method.
  if (isEntityList)
  {
      EntityList&lt;BusinessEntity&gt; elList = (EntityList&lt;BusinessEntity&gt;)pi.GetValue(this, null);
      foreach (BusinessEntity beEntity in elList)
          returnValue += beEntity.GetChanges(messageFormat, stopAtFirstDifference);
  }
  </code></pre>
  
  <p>But I'm getting a cast exception when doing</p>
  
  <pre><code>EntityList&lt;BusinessEntity&gt; elList = (EntityList&lt;BusinessEntity&gt;)pi.GetValue(this, null);
  </code></pre>
  
  <p>Ah! I think my problem is C# 3.5 does not accept covariance (something new to me, and existent in 4.0). So I had to expose a property with the list as BusinessEntities</p>
  
  <p>At EntityList where BE : BusinessEntity, new()</p>
  
  <pre><code>public virtual List&lt;BusinessEntity&gt; ItemsAsBE
  {
      get
      {
          List&lt;BusinessEntity&gt; returnValue = new List&lt;BusinessEntity&gt;(this.Items.Count);
          foreach (BusinessEntity item in this.Items)
              returnValue.Add(item);
          return returnValue;
      }
  }
  </code></pre>
  
  <p>and at BusinessEntity</p>
  
  <pre><code>// If property is a subclass of EntityList, invoke GetChanges method.
  if (isEntityList)
  {
      foreach (BusinessEntity beEntity in thisType.GetProperty("ItemsAsBE").GetValue(pi.GetValue(this, null), null) as List&lt;BusinessEntity&gt;)
          returnValue += beEntity.GetChanges(messageFormat, stopAtFirstDifference);
  }
  </code></pre>
  
  <p>Thanks everyone! Hope this help someone in the future!</p>