How to know if a object is derived from BusinessListBase?

How to know if a object is derived from BusinessListBase?

Old forum URL: forums.lhotka.net/forums/t/4998.aspx


longbridge posted on Saturday, June 21, 2008

Hi,

I need to test if the type of a object is a subclass of BusinessListBase without giving the specific type of T and C. Since BusinessListBase is a generic class defined as:
 
public abstract class BusinessListBase<T, C> : ExtendedBindingList<C>, IEditableCollection, IBusinessObject, ISupportUndo, IUndoableObject, ICloneable, ISavable, IParent
        where T : Csla.BusinessListBase<T, C>
        where C : Csla.Core.IEditableBusinessObject


how can I do that?

For BusinessBase, I can use
if(myObject is BusinessBase) { ... }

But for BusinessListBase, following code can not pass compilation.

if(myObject is BusinessListBase<BusinessListBase, IEditableBusinessObject>)
{ ... }

Thanks.

simon_may replied on Saturday, June 21, 2008

I have looked at this type of problem many times and have never been able to find a 'generic' solution to it. I am sure that there must be one somewhere. Having given up on that, I check for Csla.Core.IEditableCollection a non generic interface unique to the BusinessListBase.

Simon

longbridge replied on Saturday, June 21, 2008

Thanks. Simon.

Actually I would like to get IsValid property after I convert myObject to BusinessListBase(if the type test can pass). IEditableCollection doesn't has isValid property, so it doesn't work for my case.

Actually this is a general problem for generic type. There should be a solution to do that.


tmg4340 replied on Saturday, June 21, 2008

There are properties on a Type object that would tell you whether it is a generic type.  But you aren't going to get what you want.

The reason there is no solution for this is because BusinessListBase<T, C> is what's called an "open generic type" - a type whose generic parameters have not been resolved down to actual types.  Generics are essentially a compiler trick, and do not work like base classes.  They are more like C++ templates.  That's why Rocky had to create the interfaces.  As such, there is no "BusinessListBase<T, C>" type anywhere.  Every reference is resolved to its "closed type" based on what you provide for T and C.  So it's not possible to cast a variable to "BusinessListBase<T, C>".

Also, consider what would have to happen if .NET allowed you to cast a variable to a "BusinessListBase<T, C>" type.  How does it work with T and C within the generic type when it doesn't know what they are?  Sure, there could be constraints on the generic types, but .NET can't guarantee that.  And those types may play into the properties/methods you're trying to use.

What version of CSLA are you working with?  The 3.0 version I have shows that "IsValid" is part of the "IEditableCollection" interface...

HTH

- Scott

simon_may replied on Sunday, June 22, 2008

Thanks Scott. As I said before, I have looked at the problem on a number of occasions but have never come to a firm conclusion. Your explanation makes perfect sense and is pretty much what I imagined it might be without thinking it through to a firm conclusion

Simon

sergeyb replied on Sunday, June 22, 2008

This maybe a bit convuluted, but here it goes anyway :-)

 

public static bool IsBusinessListBase(object testObject)

{

bool returnValue = false;

if (testObject.GetType().BaseType.GetGenericArguments().Length==2)

{

Type firstParameter = testObject.GetType().BaseType.GetGenericArguments()[0].UnderlyingSystemType;

Type secondParameter = testObject.GetType().BaseType.GetGenericArguments()[1].UnderlyingSystemType;

Type[] interfaces = secondParameter.GetInterfaces();

bool isEditableObject = false;

for (int intefaceCounter = 0; intefaceCounter < interfaces.Length-1; intefaceCounter++)

{

if (interfaces[intefaceCounter].UnderlyingSystemType.Equals(typeof(System.ComponentModel.IEditableObject)))

{

isEditableObject = true;

}

}

if (isEditableObject)

{

Type businessListType = typeof(BusinessListBase<,>).MakeGenericType(new Type[] { firstParameter, secondParameter });

if (testObject.GetType().BaseType.Equals(businessListType))

{

returnValue = true;

}

}

}

return returnValue;

}

RockfordLhotka replied on Monday, June 23, 2008

The Csla.Core.ITrackStatus interface introduced in CSLA .NET 3.5 should give you IsValid, along with other important status properties.

You'll still need to check to see if the type implements IEditableCollection to know if it is a BLB.

longbridge replied on Monday, June 23, 2008


Thanks for all your replies.

For my problem, I can use IEditableCollection to test the object and get isValid Property if type is compatible.

Kevin

JoeFallon1 replied on Sunday, June 22, 2008

longbridge:
Actually I would like to get IsValid property after I convert myObject to BusinessListBase(if the type test can pass). IEditableCollection doesn't has isValid property, so it doesn't work for my case.

I had this exact same issue.

I simply created my own Interface which Inherits IEditableCollection and then exposed IsValid.

Then I had my base class which derives from BusinessListBase implement my Interface.

Thus all of my collections implement the Interface and I can cast any list to the Interface and ask if it IsValid.

I also added a few more things that I needed while I was doing this. This process allowed me to develop a general report engine using DataDynamics reporting where the detail section is *any* ROC.

Joe

 

 

Copyright (c) Marimer LLC