开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜