crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Base/CIElement.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 * 
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 using System;
       
    18 using System.Text;
       
    19 using System.Reflection;
       
    20 using System.Collections.Generic;
       
    21 using SymbianUtils;
       
    22 using SymbianDebugLib.Engine;
       
    23 using CrashItemLib.Engine;
       
    24 using CrashItemLib.Crash;
       
    25 using CrashItemLib.Crash.Messages;
       
    26 using CrashItemLib.Crash.Container;
       
    27 using CrashItemLib.Crash.Base.DataBinding;
       
    28 
       
    29 namespace CrashItemLib.Crash.Base
       
    30 {
       
    31 	public abstract class CIElement : IEnumerable<CIElement>
       
    32     {
       
    33         #region Delegates & events
       
    34         public delegate void CIElementEventHandler( CIElement aElement );
       
    35         public delegate void CIMultiElementEventHandler( CIElement aSelf, CIElement aOther );
       
    36 
       
    37         public event CIMultiElementEventHandler ChildAdded = null;
       
    38         #endregion
       
    39 
       
    40         #region Enumerations
       
    41         internal enum TAutoPopulateType
       
    42         {
       
    43             EAutoPopulateDisabled = 0,
       
    44             EAutoPopulateEnabled
       
    45         }
       
    46 
       
    47         public enum TChildSearchType
       
    48         {
       
    49             EDirectChildrenOnly = 0,
       
    50             EEntireHierarchy
       
    51         }
       
    52         #endregion
       
    53 
       
    54         #region Constructors
       
    55         internal CIElement( int aId )
       
    56             : this( aId, false )
       
    57         {
       
    58             // NB: to be called only by the container itself since everything else
       
    59             // must specify a valid container object
       
    60             System.Diagnostics.Debug.Assert( this is CIContainer );
       
    61         }
       
    62 
       
    63         internal CIElement( CIContainer aContainer )
       
    64             : this( aContainer, TAutoPopulateType.EAutoPopulateDisabled )
       
    65 		{
       
    66 		}
       
    67 
       
    68         internal CIElement( CIContainer aContainer, CIElement aParent )
       
    69             : this( aContainer )
       
    70         {
       
    71             iParent = aParent;
       
    72         }
       
    73 
       
    74         internal CIElement( CIContainer aContainer, TAutoPopulateType aDataBindingAutoPopulate )
       
    75             : this( aContainer.GetNextElementId(), aDataBindingAutoPopulate == TAutoPopulateType.EAutoPopulateEnabled )
       
    76         {
       
    77             iContainer = aContainer;
       
    78         }
       
    79 
       
    80         internal CIElement( CIContainer aContainer, CIElement aParent, TAutoPopulateType aDataBindingAutoPopulate )
       
    81             : this( aContainer, aDataBindingAutoPopulate )
       
    82         {
       
    83             iParent = aParent;
       
    84         }
       
    85         
       
    86         private CIElement( long aId, bool aDataBindingAutoPopulate )
       
    87         {
       
    88             iId = new CIElementId( aId );
       
    89             iDataBindingModel = new CIDBModel( this, aDataBindingAutoPopulate );
       
    90         }
       
    91         #endregion
       
    92 
       
    93         #region API - Framework Properties
       
    94         public virtual string Name
       
    95         {
       
    96             get { return string.Empty; }
       
    97             set { }
       
    98         }
       
    99 
       
   100         public virtual CIElementId Id
       
   101         {
       
   102             get { return iId; }
       
   103             set 
       
   104             { 
       
   105                 iId = value;
       
   106                 IsIdExplicit = true;
       
   107             }
       
   108         }
       
   109         #endregion
       
   110 
       
   111         #region API - Children
       
   112         public virtual int Count
       
   113         {
       
   114             get 
       
   115             {
       
   116                 int ret = 0;
       
   117                 //
       
   118                 lock ( iSyncLock )
       
   119                 {
       
   120                     if ( iChildren != null )
       
   121                     {
       
   122                         ret = iChildren.Count;
       
   123                     }
       
   124                 }
       
   125                 //
       
   126                 return ret;
       
   127             }
       
   128         }
       
   129 
       
   130         public bool HasChildren
       
   131         {
       
   132             get
       
   133             {
       
   134                 bool ret = false;
       
   135                 //
       
   136                 lock ( iSyncLock )
       
   137                 {
       
   138                     if ( iChildren != null )
       
   139                     {
       
   140                         ret = ( iChildren.Count > 0 );
       
   141                     }
       
   142                 }
       
   143                 //
       
   144                 return ret;
       
   145             }
       
   146         }
       
   147 
       
   148         public virtual void AddChild( CIElement aChild )
       
   149         {
       
   150             if ( aChild != null )
       
   151             {
       
   152                 // If we have been restricted to a specific 
       
   153                 // type of child element, then check aChild against
       
   154                 // it...
       
   155                 Type t = aChild.GetType();
       
   156                 ValidateChildType( t );
       
   157 
       
   158                 lock ( iSyncLock )
       
   159                 {
       
   160                     if ( iChildren == null )
       
   161                     {
       
   162                         iChildren = new CIElementList<CIElement>( Container );
       
   163                         iChildren.IsInContainer = this.IsInContainer;
       
   164                     }
       
   165 
       
   166                     if ( aChild.Parent == null )
       
   167                     {
       
   168                         aChild.Parent = this;
       
   169                     }
       
   170 
       
   171                     iChildren.Add( aChild );
       
   172                 }
       
   173 
       
   174                 OnElementAddedToSelf( aChild );
       
   175             }
       
   176         }
       
   177 
       
   178         public virtual void AddChildren( CIElement[] aChildren )
       
   179         {
       
   180             for ( int i = aChildren.Length - 1; i >= 0; i-- )
       
   181             {
       
   182                 AddChild( aChildren[ i ] );
       
   183             }
       
   184         }
       
   185 
       
   186         public virtual void RemoveChild( CIElement aChild )
       
   187         {
       
   188             if ( aChild == null )
       
   189             {
       
   190                 throw new ArgumentException( "Child is null" );
       
   191             }
       
   192 
       
   193             if ( HasChildren && iChildren.Count > 0 )
       
   194             {
       
   195                 lock ( iSyncLock )
       
   196                 {
       
   197                     iChildren.Remove( aChild );
       
   198                 }
       
   199             }
       
   200         }
       
   201 
       
   202         public virtual void RemoveChildren( Type aType )
       
   203         {
       
   204             if ( HasChildren && iChildren.Count > 0 )
       
   205             {
       
   206                 lock ( iSyncLock )
       
   207                 {
       
   208                     int count = iChildren.Count;
       
   209                     for ( int i = count - 1; i >= 0; i-- )
       
   210                     {
       
   211                         CIElement child = iChildren[ i ];
       
   212                         if ( aType.IsAssignableFrom( aType ) )
       
   213                         {
       
   214                             iChildren.Remove( child );
       
   215                         }
       
   216                     }
       
   217                 }
       
   218             }
       
   219         }
       
   220 
       
   221         public virtual void Clear()
       
   222         {
       
   223             lock ( iSyncLock )
       
   224             {
       
   225                 if ( iChildren != null )
       
   226                 {
       
   227                     iChildren.Clear();
       
   228                 }
       
   229             }
       
   230         }
       
   231 
       
   232         public virtual bool Contains( CIElement aElement )
       
   233         {
       
   234             return Contains( aElement.Id );
       
   235         }
       
   236 
       
   237         public virtual bool Contains( CIElementId aId )
       
   238         {
       
   239             bool ret = false;
       
   240             //
       
   241             lock ( iSyncLock )
       
   242             {
       
   243                 if ( iChildren != null )
       
   244                 {
       
   245                     ret = iChildren.Contains( aId );
       
   246                 }
       
   247             }
       
   248             //
       
   249             return ret;
       
   250         }
       
   251 
       
   252         public CIElement this[ CIElementId aId ]
       
   253         {
       
   254             get
       
   255             {
       
   256                 CIElement ret = null;
       
   257                 //
       
   258                 lock ( iSyncLock )
       
   259                 {
       
   260                     if ( Contains( aId ) )
       
   261                     {
       
   262                         System.Diagnostics.Debug.Assert( iChildren != null );
       
   263                         ret = iChildren[ aId ];
       
   264                     }
       
   265                 }
       
   266                 //
       
   267                 return ret;
       
   268             }
       
   269         }
       
   270 
       
   271         public CIElement this[ int aIndex ]
       
   272         {
       
   273             get
       
   274             {
       
   275                 CIElement ret = null;
       
   276                 //
       
   277                 lock ( iSyncLock )
       
   278                 {
       
   279                     if ( iChildren != null )
       
   280                     {
       
   281                         ret = iChildren[ aIndex ];
       
   282                     }
       
   283                 }
       
   284                 //
       
   285                 return ret;
       
   286             }
       
   287         }
       
   288         
       
   289         public CIElement ChildByType( Type aType )
       
   290         {
       
   291             CIElement ret = null;
       
   292             //
       
   293             lock ( iSyncLock )
       
   294             {
       
   295                 foreach ( CIElement element in this )
       
   296                 {
       
   297                     if ( aType.IsAssignableFrom( element.GetType() ) )
       
   298                     {
       
   299                         ret = element;
       
   300                         break;
       
   301                     }
       
   302                 }
       
   303             }
       
   304             //
       
   305             return ret;
       
   306         }
       
   307 
       
   308         public CIElementList<T> ChildrenByType<T>() where T: CIElement
       
   309         {
       
   310             CIElementList<T> ret = ChildrenByType<T>( TChildSearchType.EDirectChildrenOnly );
       
   311             return ret;
       
   312         }
       
   313 
       
   314         public CIElementList<T> ChildrenByType<T>( Predicate<T> aPredicate ) where T : CIElement
       
   315         {
       
   316             CIElementList<T> ret = ChildrenByType<T>( TChildSearchType.EDirectChildrenOnly, aPredicate );
       
   317             return ret;
       
   318         }
       
   319 
       
   320         public CIElementList<T> ChildrenByType<T>( TChildSearchType aType ) where T : CIElement
       
   321         {
       
   322             return ChildrenByType<T>( aType, null );
       
   323         }
       
   324 
       
   325         public CIElementList<T> ChildrenByType<T>( TChildSearchType aType, Predicate<T> aPredicate ) where T : CIElement
       
   326         {
       
   327             CIElementList<T> ret = new CIElementList<T>( Container );
       
   328             GetChildrenByType<T>( ret, aType, aPredicate );
       
   329             return ret;
       
   330         }
       
   331 
       
   332         internal CIElementList<CIElement> Children
       
   333         {
       
   334             get
       
   335             {
       
   336                 CIElementList<CIElement> ret = null;
       
   337                 //
       
   338                 lock ( iSyncLock )
       
   339                 {
       
   340                     ret = iChildren;
       
   341                     //
       
   342                     if ( ret == null )
       
   343                     {
       
   344                         ret = new CIElementList<CIElement>( Container );
       
   345                     }
       
   346                 }
       
   347                 //
       
   348                 return ret;
       
   349             }
       
   350         }
       
   351         #endregion
       
   352 
       
   353         #region API - Data Binding framework
       
   354         public virtual void PrepareColumns()
       
   355         {
       
   356             DataBindingModel.ClearColumns();
       
   357             DataBindingModel.TryAutoPopulateColumns( this );
       
   358         }
       
   359 
       
   360         public virtual void PrepareRows()
       
   361         {
       
   362             DataBindingModel.ClearRows();
       
   363             DataBindingModel.TryAutoPopulateCells( this );
       
   364         }
       
   365         #endregion
       
   366 
       
   367         #region API - Parentage
       
   368         public bool HasParent
       
   369         {
       
   370             get
       
   371             {
       
   372                 lock ( iSyncLock )
       
   373                 {
       
   374                     return iParent != null;
       
   375                 }
       
   376             }
       
   377         }
       
   378 
       
   379         public virtual CIElement Parent
       
   380         {
       
   381             get
       
   382             {
       
   383                 lock ( iSyncLock )
       
   384                 {
       
   385                     return iParent;
       
   386                 }
       
   387             }
       
   388             internal set 
       
   389             {
       
   390                 lock ( iSyncLock )
       
   391                 {
       
   392                     iParent = value;
       
   393                 }
       
   394             }
       
   395         }
       
   396         #endregion
       
   397 
       
   398         #region Properties
       
   399         public virtual bool IsInContainer
       
   400         {
       
   401             get
       
   402             {
       
   403                 lock ( iSyncLock )
       
   404                 {
       
   405                     return ( iFlags & TFlags.EFlagsIsInContainer ) == TFlags.EFlagsIsInContainer;
       
   406                 }
       
   407             }
       
   408             internal set
       
   409             {
       
   410                 // Don't allow it to change if we're locked down.
       
   411                 if ( IsFinalized == false )
       
   412                 {
       
   413                     bool oldValue = IsInContainer;
       
   414                     if ( oldValue != value )
       
   415                     {
       
   416                         // Set new flag value
       
   417                         lock ( iSyncLock )
       
   418                         {
       
   419                             if ( value )
       
   420                             {
       
   421                                 iFlags |= TFlags.EFlagsIsInContainer;
       
   422                             }
       
   423                             else
       
   424                             {
       
   425                                 iFlags &= ~TFlags.EFlagsIsInContainer;
       
   426                             }
       
   427                         }
       
   428 
       
   429                         // Fire internal call that reflects new state. This notifies the
       
   430                         // container about our registration status and in turn, the container
       
   431                         // can notify it's observers about our presence/remove within container.
       
   432                         OnIsInContainerChanged();
       
   433 
       
   434                         // Ensure children are also in/out of container
       
   435                         lock ( iSyncLock )
       
   436                         {
       
   437                             if ( iChildren != null )
       
   438                             {
       
   439                                 iChildren.IsInContainer = value;
       
   440                             }
       
   441                         }
       
   442                     }
       
   443                 }
       
   444             }
       
   445         }
       
   446 
       
   447         public bool IsIdExplicit
       
   448         {
       
   449             get
       
   450             {
       
   451                 lock ( iSyncLock )
       
   452                 {
       
   453                     return ( iFlags & TFlags.EFlagsIdWasExplicitlySet ) == TFlags.EFlagsIdWasExplicitlySet;
       
   454                 }
       
   455             }
       
   456             private set 
       
   457             {
       
   458                 lock ( iSyncLock )
       
   459                 {
       
   460                     if ( value )
       
   461                     {
       
   462                         iFlags |= TFlags.EFlagsIdWasExplicitlySet;
       
   463                     }
       
   464                     else
       
   465                     {
       
   466                         iFlags &= ~TFlags.EFlagsIdWasExplicitlySet;
       
   467                     }
       
   468                 }
       
   469             }
       
   470         }
       
   471 
       
   472         public virtual CIEngine Engine
       
   473         {
       
   474             get { return Container.Engine; }
       
   475         }
       
   476 
       
   477         public CIContainer Container
       
   478         {
       
   479             get
       
   480             {
       
   481                 lock ( iSyncLock )
       
   482                 {
       
   483                     return iContainer;
       
   484                 }
       
   485             }
       
   486             internal set 
       
   487             {
       
   488                 lock ( iSyncLock )
       
   489                 {
       
   490                     iContainer = value;
       
   491                 }
       
   492             }
       
   493         }
       
   494 
       
   495         public CIDBModel DataBindingModel
       
   496         {
       
   497             get { return iDataBindingModel; }
       
   498         }
       
   499 
       
   500         protected bool IsToBeFinalizedLast
       
   501         {
       
   502             get
       
   503             {
       
   504                 lock ( iSyncLock )
       
   505                 {
       
   506                     return ( iFlags & TFlags.EFlagsIsToBeFinalizedLast ) == TFlags.EFlagsIsToBeFinalizedLast;
       
   507                 }
       
   508             }
       
   509             set
       
   510             {
       
   511                 lock ( iSyncLock )
       
   512                 {
       
   513                     if ( value )
       
   514                     {
       
   515                         iFlags |= TFlags.EFlagsIsToBeFinalizedLast;
       
   516                     }
       
   517                     else
       
   518                     {
       
   519                         iFlags &= ~TFlags.EFlagsIsToBeFinalizedLast;
       
   520                     }
       
   521                 }
       
   522             }
       
   523         }
       
   524 
       
   525         internal bool IsFinalized
       
   526         {
       
   527             get
       
   528             {
       
   529                 lock ( iSyncLock )
       
   530                 {
       
   531                     return ( iFlags & TFlags.EFlagsIsFinalized ) == TFlags.EFlagsIsFinalized;
       
   532                 }
       
   533             }
       
   534             set
       
   535             {
       
   536                 lock ( iSyncLock )
       
   537                 {
       
   538                     if ( value )
       
   539                     {
       
   540                         iFlags |= TFlags.EFlagsIsFinalized;
       
   541                     }
       
   542                     else
       
   543                     {
       
   544                         iFlags &= ~TFlags.EFlagsIsFinalized;
       
   545                     }
       
   546                 }
       
   547             }
       
   548         }
       
   549         #endregion
       
   550 
       
   551         #region Internal methods
       
   552         internal void Trace( string aMessage )
       
   553         {
       
   554             Container.Engine.Trace( aMessage );
       
   555         }
       
   556 
       
   557         internal void Trace( string aFormat, params object[] aParams )
       
   558         {
       
   559             Container.Engine.Trace( aFormat, aParams );
       
   560         }
       
   561 
       
   562         protected void AddSupportedChildType( Type aType )
       
   563         {
       
   564             lock ( iSyncLock )
       
   565             {
       
   566                 if ( iSupportedChildTypes == null )
       
   567                 {
       
   568                     iSupportedChildTypes = new List<Type>();
       
   569                 }
       
   570                 iSupportedChildTypes.Add( aType );
       
   571             }
       
   572         }
       
   573 
       
   574         private void ValidateChildType( Type aType )
       
   575         {
       
   576             lock ( iSyncLock )
       
   577             {
       
   578                 if ( iSupportedChildTypes != null )
       
   579                 {
       
   580                     StringBuilder typeNames = new StringBuilder();
       
   581                     //
       
   582                     foreach ( Type t in iSupportedChildTypes )
       
   583                     {
       
   584                         typeNames.Append( t.ToString() + ", " );
       
   585                         //
       
   586                         if ( aType == t || aType.IsSubclassOf( t ) )
       
   587                         {
       
   588                             return;
       
   589                         }
       
   590                     }
       
   591                     //
       
   592                     string names = typeNames.ToString();
       
   593                     if ( names.Length > 2 )
       
   594                     {
       
   595                         names = names.Substring( 0, names.Length - 2 );
       
   596                     }
       
   597                     //
       
   598                     throw new ArgumentException( "Child is not of type: [" + names + "]" );
       
   599                 }
       
   600             }
       
   601         }
       
   602 
       
   603         internal virtual void GetChildrenByType<T>( CIElementList<T> aList, TChildSearchType aType, Predicate<T> aPredicate ) where T : CIElement
       
   604         {
       
   605             // Get all direct children, and if recusion enabled, then fetch the
       
   606             // entire tree.
       
   607             Type t = typeof( T );
       
   608             foreach ( CIElement element in Children )
       
   609             {
       
   610                 if ( t.IsAssignableFrom( element.GetType() ) )
       
   611                 {
       
   612                     // Get entry of correct type
       
   613                     T objectEntry = (T) ( (object) element );
       
   614 
       
   615                     // Check whether it is suitable for inclusion via our predicate
       
   616                     bool addEntry = true;
       
   617                     if ( aPredicate != null )
       
   618                     {
       
   619                         addEntry = aPredicate( objectEntry );
       
   620                     }
       
   621                     
       
   622                     // Is it okay to take the entry?
       
   623                     if ( addEntry )
       
   624                     {
       
   625                         aList.Add( objectEntry );
       
   626                     }
       
   627                 }
       
   628 
       
   629                 // Get the element's children
       
   630                 if ( aType == TChildSearchType.EEntireHierarchy )
       
   631                 {
       
   632                     element.GetChildrenByType<T>( aList, aType, aPredicate );
       
   633                 }
       
   634             }
       
   635         }
       
   636         #endregion
       
   637 
       
   638         #region Internal flags
       
   639         [Flags]
       
   640         private enum TFlags : short
       
   641         {
       
   642             EFlagsNone = 0,
       
   643             EFlagsIsInContainer = 1,
       
   644             EFlagsIdWasExplicitlySet = 2,
       
   645             EFlagsIsReadOnly = 4,
       
   646             EFlagsIsToBeFinalizedLast = 8,
       
   647             EFlagsIsFinalized = 16,
       
   648         }
       
   649         #endregion
       
   650 
       
   651         #region Internal framework methods
       
   652         /// <summary>
       
   653         /// Called when the element is to finish its construction. At this point
       
   654         /// it is assumed that the crash container data structure is largely fully
       
   655         /// populated. This function call should typically perform any final 
       
   656         /// post-processing, such as looking up symbols etc.
       
   657         /// </summary>
       
   658         /// <param name="aParams"></param>
       
   659         internal virtual void OnFinalize( CIElementFinalizationParameters aParams )
       
   660         {
       
   661         }
       
   662 
       
   663         internal void DoFinalizeElements( CIElementFinalizationParameters aParams, Queue<CIElement> aCallBackLast, bool aForceFinalize, IEnumerable<CIElement> aElements )
       
   664         {
       
   665             foreach( CIElement element in aElements )
       
   666             {
       
   667                 if ( element.IsToBeFinalizedLast )
       
   668                 {
       
   669                     aCallBackLast.Enqueue( element );
       
   670                 }
       
   671                 //
       
   672                 element.DoFinalize( aParams, aCallBackLast, aForceFinalize );
       
   673             }
       
   674         }
       
   675 
       
   676         internal virtual void DoFinalize( CIElementFinalizationParameters aParams, Queue<CIElement> aCallBackLast, bool aForceFinalize )
       
   677         {
       
   678             lock ( iSyncLock )
       
   679             {
       
   680                 // Finalize children
       
   681                 if ( iChildren != null )
       
   682                 {
       
   683                     DoFinalizeElements( aParams, aCallBackLast, aForceFinalize, iChildren );
       
   684                 }
       
   685             }
       
   686 
       
   687             // Finalize ourself
       
   688             if ( ( aForceFinalize || IsToBeFinalizedLast == false ) && IsFinalized == false )
       
   689             {
       
   690                 try
       
   691                 {
       
   692                     OnFinalize( aParams );
       
   693                 }
       
   694                 finally
       
   695                 {
       
   696                     IsFinalized = true;
       
   697                 }
       
   698             }
       
   699         }
       
   700 
       
   701         /// <summary>
       
   702         /// Called by CIElement.AddChild() whenever a new element is
       
   703         /// added as a child of this element.
       
   704         /// 
       
   705         /// Notify the container that a child entry was added
       
   706         /// so that it can notify any elements that listen to
       
   707         /// all additions to the container (direct or indirect).
       
   708         /// </summary>
       
   709         protected virtual void OnElementAddedToSelf( CIElement aElement )
       
   710         {
       
   711             // aElement inherits our container state
       
   712             bool inContainer = IsInContainer;
       
   713 
       
   714             // Doing this will fire an added/removed event in accordance
       
   715             // with what our state currently is and what it has just become.
       
   716             aElement.IsInContainer = inContainer;
       
   717 
       
   718             // Report event
       
   719             if ( ChildAdded != null )
       
   720             {
       
   721                 ChildAdded( this, aElement );
       
   722             }
       
   723         }
       
   724 
       
   725         protected virtual void OnIsInContainerChanged()
       
   726         {
       
   727             // If we're now in the container, either directly or indirectly (we don't care)
       
   728             // then make sure we notify the container so that it can inform other elements
       
   729             // that may be listening.
       
   730             //
       
   731             // Because "IsInContainer" cascades changes to our children, they will also
       
   732             // notify the container themselves in due course.
       
   733             //
       
   734             // Obviously don't cascade when the container itself changes its state.
       
   735             if ( this != Container )
       
   736             {
       
   737                 if ( IsInContainer )
       
   738                 {
       
   739                     Container.OnContainerElementRegistered( this );
       
   740                 }
       
   741                 else
       
   742                 {
       
   743                     Container.OnContainerElementUnregistered( this );
       
   744                 }
       
   745             }
       
   746         }
       
   747         #endregion
       
   748 
       
   749         #region From System.Object
       
   750         public override string ToString()
       
   751         {
       
   752             return Name;
       
   753         }
       
   754         #endregion
       
   755 
       
   756         #region From IEnumerable<CIElement>
       
   757         public IEnumerator<CIElement> GetEnumerator()
       
   758         {
       
   759             lock ( iSyncLock )
       
   760             {
       
   761                 CIElementList<CIElement> children = iChildren;
       
   762                 if ( iChildren == null )
       
   763                 {
       
   764                     children = new CIElementList<CIElement>( Container );
       
   765                 }
       
   766                 return children.GetEnumerator();
       
   767             }
       
   768         }
       
   769 
       
   770         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
       
   771         {
       
   772             lock ( iSyncLock )
       
   773             {
       
   774                 CIElementList<CIElement> children = iChildren;
       
   775                 if ( iChildren == null )
       
   776                 {
       
   777                     children = new CIElementList<CIElement>( Container );
       
   778                 }
       
   779                 return children.GetEnumerator();
       
   780             }
       
   781         }
       
   782         #endregion
       
   783 
       
   784         #region Data members
       
   785         private readonly CIDBModel iDataBindingModel;
       
   786         private object iSyncLock = new object();
       
   787         private CIElement iParent = null;
       
   788         private List<Type> iSupportedChildTypes = null;
       
   789         private CIContainer iContainer;
       
   790         private CIElementList<CIElement> iChildren;
       
   791         private CIElementId iId = new CIElementId();
       
   792         private TFlags iFlags = TFlags.EFlagsNone;
       
   793 		#endregion
       
   794     }
       
   795 }