473,721 Members | 1,778 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Reflecting generic collections of derived types

5 New Member
I am trying to use reflection in a property of a base type to inspect the properties of an instance of a type which is derived from that base type, when the properties can themselves be instances of types derived from that base type, or arrays or generic collections of instances of types derived from that base type.

All is well until I come to the properties which are generic collections, I don't seem to be able to find an elegant way of inspecting these.

Here is some code to illustrate what I'm trying to do. The base type, and therefore the derived types, have an ErrorState property, this is an enumeration of things which could be wrong with instances of those types. There is also a ConsolidatedSta te property, this is the one which uses reflection to return a combination of all the things which may be wrong with the current instance and all of its properties.

Expand|Select|Wrap|Line Numbers
  1.  
  2. [Flags]
  3. public enum ErrorState
  4. {
  5.     Ok = 1,
  6.     ConnectionError = 2,
  7.     HoustonWeHaveAProblem = 4
  8.     // etc...
  9. }
  10.  
  11. public abstract class MyBase
  12. {
  13.     private ErrorState _errorState;
  14.  
  15.     public ErrorState ErrorState
  16.     {
  17.         get { return _errorState; }
  18.         set { _errorState = value; }
  19.     }
  20.  
  21.     public ErrorState ConsolidatedState
  22.     {
  23.         get
  24.         {
  25.             ErrorState state = this.ErrorState;
  26.             PropertyInfo[] properties = this.GetType().GetProperties();
  27.             foreach( PropertyInfo property in properties )
  28.             {
  29.                 // We don't want to inspect the ConsolidatedState property
  30.                 // (this property) else we get stuck in a loop, causing a
  31.                 // StackOverflowException.
  32.                 if( property.Name == "ConsolidatedState" )
  33.                 {
  34.                     continue;
  35.                 }
  36.  
  37.                 // Is this property an array?
  38.                 if( property.PropertyType.IsArray )
  39.                 {
  40.                     // Is this property an array of objects derived from 
  41.                     // MyBase?
  42.                     MyBase[] componentArray 
  43.                         = property.GetValue( this, null ) as MyBase[];
  44.                     if( componentArray != null )
  45.                     {
  46.                         // Yes, so inspect their ConsolidatedState properties.
  47.                         foreach( MyBase c in componentArray )
  48.                         {
  49.                             state |= c.ConsolidatedState;
  50.                         }
  51.                     }
  52.                     continue;
  53.                 }
  54.  
  55.                 // Is this property an indexer?
  56.                 if( property.GetIndexParameters().Length > 0 )
  57.                 {
  58.                     // it's probably an indexer, so ignore it
  59.                     continue;
  60.                 }
  61.  
  62.                 // Is this property of a type derived from MyBase?
  63.                 if( property.PropertyType.IsSubclassOf( typeof( MyBase ) ) )
  64.                 {
  65.                     // Yes, so it also has a ConsolidatedState property
  66.                     MyBase component 
  67.                         = property.GetValue( this, null ) as MyBase;
  68.                     if( component != null )
  69.                     {
  70.                         state |= component.ConsolidatedState;
  71.                     }
  72.                     continue;
  73.                 }
  74.  
  75.                 // Is this property a generic type?
  76.                 if( property.PropertyType.IsGenericType )
  77.                 {
  78.                     // Is this property a generic collection of a type
  79.                     // derived from MyBase?
  80.                     //Collection<MyBase> componentCollection
  81.                     //    = property.GetValue( this, null ) 
  82.                     //    as Collection<MyBase>; // returns null
  83.  
  84.                     // Is this property a generic collection of MyDerived1?
  85.                     IEnumerable<MyDerived1> componentCollection 
  86.                         = property.GetValue( this, null )
  87.                         as IEnumerable<MyDerived1>;
  88.                     if( componentCollection != null )
  89.                     {
  90.                         // Yes, so inspect their ConsolidatedState properties.
  91.                         foreach( MyBase c in componentCollection )
  92.                         {
  93.                             state |= c.ConsolidatedState;
  94.                         }
  95.                     }
  96.                     continue;
  97.                 }
  98.  
  99.             }
  100.             return state;
  101.         }
  102.     }
  103. }
  104.  
  105. public class MyDerived1 : MyBase
  106. {
  107.     // ...
  108. }
  109.  
  110. public class MyDerived2 : MyBase
  111. {
  112.     public MyDerived1 Property1
  113.     {
  114.         get { return new MyDerived1(); }
  115.     }
  116.  
  117.     public MyDerived1[] Property2
  118.     {
  119.         get { return new MyDerived1[4]; }
  120.     }
  121.  
  122.     public Collection<MyDerived1> Property3
  123.     {
  124.         get { return new Collection<MyDerived1>(); }
  125.     }
  126. }
  127.  
  128.  
The problem is with this line, which I've commented out in the ConsolidatedSta te property of MyBase:

// Is this property a generic collection of a type
// derived from MyBase?
Collection<MyBa se> componentCollec tion
= property.GetVal ue( this, null )
as Collection<MyBa se>; // returns null

Having determined that the property being inspected is a generic collection, I want to know whether the items in the collection are of a type which is derived from MyBase and therefore has an ErrorState.

Having read Casting generic collections & inheritance in the archive forum, I understand now why the cast above doesn't work. As one of the contributors to that thread succinctly puts it, a List of (Farmers) is also a List of (Persons), but a (List of Farmers) is not a (List of Persons), and I'm trying to cast a (List of Farmers) to a (List of Persons).

What I want to do is attempt to cast something which I know is a generic collection, into any sort of array / list / collection in order that I can determine whether its items are derived from MyBase and therefore whether they have a ConsolidatedSta te property.

As you can see, I came up with a solution, but it's not very elegant because it depends on MyBase knowing that one or more of its derived types has a property which is a generic collection of instances of another specific type derived from MyBase. If someone later writes another type derived from MyBase, with a property which is a generic collection of instances of a type other than MyDerived1, then its ConsolidatedSta te property won't be able to inspect that collection unless MyBase is also changed to cater for properties of that type.

I feel sure that there must be a more elegant solution than this, one in which the author of MyBase doesn't need to know any of the implementation details of any of the types derived from MyBase. Can anyone suggest one?

Thank you and apologies for a long first post.

Simon.
Jul 18 '09 #1
2 4181
icesign
5 New Member
Just check if the property is IEnumerable (non-generic version) and then cast objects to whatever you want. That way you will cover arrays too because arrays are IEnumerable.
Aug 5 '09 #2
SimonDotException
5 New Member
@icesign
Thank you!

I changed the lines within the ConsolidatedSta te property

Expand|Select|Wrap|Line Numbers
  1. // Is this property a generic collection of MyDerived1?
  2. IEnumerable<MyDerived1> componentCollection 
  3.     = property.GetValue( this, null )
  4.     as IEnumerable<MyDerived1>;
  5. if( componentCollection != null )
  6. {
  7.     // Yes, so inspect their ConsolidatedState properties.
  8.     foreach( MyBase c in componentCollection )
  9.     {
  10.         state |= c.ConsolidatedState;
  11.     }
  12. }
  13.  
to

Expand|Select|Wrap|Line Numbers
  1. // Is this property IEnumerable?
  2. IEnumerable objectCollection 
  3.     = property.GetValue( this, null ) as IEnumerable;
  4. if( objectCollection != null )
  5. {
  6.     // Yes, it's IEnumerable, so iterate through its items
  7.     foreach( object o in objectCollection )
  8.     {
  9.         // Is this item of a type derived from MyBase?
  10.         MyBase c = o as MyBase;
  11.         if( c != null )
  12.         {
  13.             // Yes, so get its ConsolidatedState property
  14.         state |= c.ConsolidatedState;
  15.         }
  16.     }
  17. }
  18.  
and it all seems to work fine now.

Thank you Icesign :-)
Aug 6 '09 #3

Sign in to post your reply or Sign up for a free account.

Similar topics

1
1839
by: Andy | last post by:
Can anyone tell me if it is possible to dynamically create generic collections? simply put I want to be able to something like this : public object test(SomeBaseClass param1) { if (param1.prop1 == "blah") { //logic to determine the type
2
2033
by: Jasper Kent | last post by:
I'm trying to do the equivalent of using typedefs with templates in C++ to avoid long instantiation names. I can do this okay: using BigDictionary = System.Collections.Generic.Dictionary<int, System.Collections.Generic.Dictionary<int, string>>; class MyClass {
2
3310
by: ljlevend | last post by:
I've noticed that in VS.NET 2.0 Beta 1 that none of the methods in System.Collections.Generic.List are overridable. In my app I currently have over 50 strongly typed ArrayLists that inherit from System.Collections.ArrayList. Each of these types raise strongly typed events for when items are added and removed (e.g., AddingItem, AddedItem, CollectionChanged, etc.). One of my hopes for v2.0 was to create a single generic List that replaces...
22
13113
by: Adam Clauss | last post by:
OK, I have class A defined as follows: class A { A(Queue<B> queue) { ... } } Now, I then have a subclass of both classes A and B. The subclass of A (SubA), more specifically is passed a Queue<SubB>.
5
7650
by: Dale | last post by:
I read an article sometime in the last few weeks comparing the performance of Generic Collections to ArrayList. It was pretty detailed with several charts comparing various collections methods between the two. I think the article was in MSDN magazine but I can't find it after hours of searching online. Does anyone remember the article? If so, would you please send a link? Thanks,
1
1622
by: Ralf Propach | last post by:
Hi, in C# I can write Type listType = typeof(System.Collections.Generic.List<>); What is the equivalent in C++? I get compiler errors for all of the following: Type listType = System::Collections::Generic::List::typeid; Type listType = System::Collections::Generic::List<>::typeid; Type listType = __typeof(System::Collections::Generic::List);
3
2191
by: Boris | last post by:
I have a class which should like this ideally: generic <typename T> public ref class ManagedClass { T ^managedMember; UnmanagedClass<U*unmanagedMember; }; I actually would like to specify the type U depending on the type T. As
26
3615
by: raylopez99 | last post by:
Here is a good example that shows generic delegate types. Read this through and you'll have an excellent understanding of how to use these types. You might say that the combination of the generic delegate type expression in just the right place and a well-named method means we can almost read the code out loud and understand it without even thinking. Note that since 'boxing' and 'unboxing' is involved (I think), you don't get what you...
0
2983
by: SimonDotException | last post by:
I've written an abstract base type which uses generics to provide XML serialization and deserialization methods for use by its derived types, but I'm seemingly unable to write it in a way which completely satisfies FxCop code analysis. Here is the simplest form of the base class which reproduces the problem: public abstract class XmlSerializableItem<T> { public string ToXml() { XmlSerializer xs = new XmlSerializer( this.GetType() );...
0
8834
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8727
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9365
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9212
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9127
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9056
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8002
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4483
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
2127
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.