Retrieve NHibernate.Collections.Generic.PersistentGenericBag as IList<T> using Reflection
I'm attempting to compare a transient object graph to an NHibernate-persisted object graph. Unfortunately my code breaks where properties of type IList<T>
are concerned. The code below works fine with instances of List<T>
, because List<T>
implements both IList<T>
AND IList
. Unfortunately, NHibernate's PersistentGenericBag only implements IList<T>
.
IList list1 = (IList)prop1.GetValue(object1, null);
IList list2 = (IList)prop2.GetValue(object2, null);
If either object1 or object2 is a PersistentGenericBag, I get an error such as:
System.Reflection.TargetInvocationException : Exception has been thrown
by the target of an invocation.
----> System.InvalidCastException : Unable to cast object of type
'NHibernate.Co开发者_如何学运维llection.Generic.PersistentGenericBag`1[MyNamespace.MyClass]'
to type 'System.Collections.Generic.List`1[MyNamespace.MyClass]'.
Is there a reliable way to retrieve the PersistentGenericBag instance as an IList<T> using reflection?
I had hoped the popular Compare .NET Objects class would help, but it fails with the exact same error.
Edit: All the answers below are on the right track. The problem was that the getter on the problematic IList<T>
property was attempting a cast to List<T>
, which obviously can't be done to a PersistentGenericBag. So, my fault for the misguided question.
EDIT: never mind. commenter is right, you CAN go straight to IList. I was focusing one the question as stated a little too hard to see the obvious even as I was coding the answer. doh!
Ok, you just need to dig a little bit deeper.
The base class of PersistentGenericBag is PersistentBag, which does implement IList.
var prop1 = typeof (Customer).GetProperty("Invoice");
// if you need it for something...
var listElementType = prop1.PropertyType.GetGenericArguments()[0];
IList list1;
object obj = prop1.GetValue(object1, null);
if(obj is PersistentBag)
{
list1 = (PersistentBag)obj;
}
else
{
list1 = (IList)obj;
}
foreach (object item in list1)
{
// do whatever you wanted.
}
Tested and works for bags. Take it to the logical conclusion for other list/set/collection types that you might encounter.
So, the short answer is; If you KNOW it is a bag, you can just cast the object first to PersistentBag and then to IList...
IList list = (PersistentBag)obj;
If you DONT KNOW then use some conditional logic as shown.
You don't need an IList
to compare two collections.
Cast to IEnumerable
instead.
精彩评论