I’m using reflection to get EntityCollection<Derived> properties from my EF4 domain entities. An example entity may have many collections that hold types which have a common base. GetValue() returns an object but I need to convert it to an EntityCollection<Base> or even just IEnumerable<Base>. But how? (oops, casting to IEnumerable does work as of C#4)
Example Model
public class Derived : Base { ... }
public class AnotherDerived : Base { ... }
public class Example : Base
{
public virtual ICollection<Derived> Items { get; set; }
public virtual ICollection<AnotherDerived> OtherItems { get; set; }
}
I have a hard time understanding casting and polymorphism. I think I was able to do this successfully with reflected DbSet<Derived> casting them to IQueryable<Base>. But with EntityCollection I cannot get the reflected object back into a usable form.
Methods
public static List<T> GetCollectedEntities<T>(this BaseEntity entity)
where T : BaseEntity
{
var result = new List<T>();
foreach (var c in GetCollections<T>(entity))
foreach (var item in (EntityCollection<T>)c) //ERROR
result.Add(item);
return result;
}
public static List<object> GetCollections<T>(this BaseEntity entity)
where T : BaseEntity
{
var collections = new List<object>();
var props = from p in entity.GetType().GetProperties()
let t = p.PropertyType
where t.IsGenericType
&& t.GetGenericTypeDefinition() == typeof(ICollection<>)
let a = t.GetGenericArguments().Single()
where a == typeof(T) || a.IsSubclassOf(typeof(T))
select p;
foreach (var p in props)
collections.Add(p.GetValue(entity, null));
return collections;
}
Real World Error
Unable to cast object of type
'System.Data.Objects.DataClasses.EntityCollection`1[HTS.Data.ServiceOrder]'
to type
'System.Data.Objects.DataClasses.EntityCollection`1[HTS.Data.IncomingServiceOrderBase]'.
It seems like the sort of thing you should be able to do, doesn’t it? But it’s not allowed, and here’s why.
EntityCollection<T>is writable, so if you cast aEntityCollection<Derived>to anEntityCollection<Base>, you can then insert Base objects into the collection. That means you now have instances of a class that isn’t Derived and isn’t a child of Derived in anEntityCollection<Derived>. What then? An iterator overEntityCollection<Derived>that expects a Derived is going to fail in all sorts of exciting ways.