void OnPopulateMemebers(object sender, EventArgs e)
        {
            if (Entity.BaseEntity != null && Entity.BaseEntity.OwnProperties.Any(p => p.Group != null && p.Group.Name == Group.Name))
            {
                throw new WXMLException(
                          string.Format(
                              "В сущности {0} описана группа {1} перекрывающая одноименную группу базовой сущности {2}.",
                              Entity.Name, Group.Name, Entity.BaseEntity.Name));
            }

            var properties = Entity.OwnProperties.Where(p => p.Group == Group);
            CodeTypeReference entityClassTypeReference = WXMLCodeDomGeneratorHelper.GetEntityClassTypeReference(_settings, Entity, false);

            var entityField = new CodeMemberField(entityClassTypeReference,
                                                  new WXMLCodeDomGeneratorNameHelper(_settings).GetPrivateMemberName("entity"));

            Members.Add(entityField);

            var ctor = new CodeConstructor
            {
                Attributes = MemberAttributes.Public
            };

            ctor.Parameters.Add(new CodeParameterDeclarationExpression(entityClassTypeReference, "entity"));
            ctor.Statements.Add(
                new CodeAssignStatement(
                    new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), entityField.Name),
                    new CodeArgumentReferenceExpression("entity")
                    ));

            Members.Add(ctor);

            foreach (var propertyDesc in properties)
            {
                var property = new CodeMemberProperty
                {
                    Name   = propertyDesc.Name,
                    Type   = propertyDesc.PropertyType.ToCodeType(_settings),
                    HasGet = true,
                    HasSet = false,
                };

                property.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodePropertyReferenceExpression(
                            new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), entityField.Name),
                            property.Name)));

                Members.Add(property);
            }
        }
        protected virtual void OnPupulateM2MRelations()
        {
            var relationDescType = new CodeTypeReference(typeof(RelationDescEx));

            #region Relation
            foreach (var relation in _entity.GetM2MRelations(false))
            {
                if (relation.Left.Entity == relation.Right.Entity)
                {
                    throw new ArgumentException("To realize m2m relation on self use SelfRelation instead.");
                }

                LinkTarget link = relation.Left.Entity == _entity ? relation.Right : relation.Left;

                var accessorName  = link.AccessorName;
                var relatedEntity = link.Entity;

                if (string.IsNullOrEmpty(accessorName))
                {
                    // существуют похожие релейшены, но не имеющие имени акссесора
                    var lst =
                        link.Entity.GetM2MRelations(false).FindAll(
                            r =>
                            r.Left != link && r.Right != link &&
                            ((r.Left.Entity == _entity && string.IsNullOrEmpty(r.Right.AccessorName)) ||
                             (r.Right.Entity == _entity && string.IsNullOrEmpty(r.Left.AccessorName))));

                    if (lst.Count > 0)
                    {
                        throw new WXMLException(
                                  string.Format(
                                      "Существуют неоднозначные связи между '{0}' и '{1}'. конкретизируйте их через accessorName.",
                                      lst[0].Left.Entity.Name, lst[0].Right.Entity.Name));
                    }
                    accessorName = relatedEntity.Name;
                }
                accessorName = WXMLCodeDomGeneratorNameHelper.GetMultipleForm(accessorName);

                var entityTypeExpression = Settings.UseTypeInProps ? WXMLCodeDomGeneratorHelper.GetEntityClassTypeReferenceExpression(_settings, relatedEntity, relatedEntity.Namespace != _entity.Namespace) : WXMLCodeDomGeneratorHelper.GetEntityNameReferenceExpression(_settings, relatedEntity, relatedEntity.Namespace != _entity.Namespace);

                var desc = new CodeObjectCreateExpression(
                    new CodeTypeReference(typeof(M2MRelationDesc)),
                    entityTypeExpression);

                var staticProperty = new CodeMemberProperty
                {
                    Name       = accessorName + "Relation",
                    HasGet     = true,
                    HasSet     = false,
                    Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static,
                    Type       = relationDescType
                };

                staticProperty.GetStatements.Add(new CodeMethodReturnStatement(
                                                     new CodeObjectCreateExpression(typeof(RelationDescEx),
                                                                                    new CodeObjectCreateExpression(typeof(EntityUnion),
                                                                                                                   WXMLCodeDomGeneratorHelper.GetEntityNameReferenceExpression(_settings, _entity, false)
                                                                                                                   ), desc)
                                                     ));

                desc.Parameters.Add(new CodePrimitiveExpression(relation.SourceFragment.Identifier));

                Members.Add(staticProperty);

                GetRelationMethods(relation.SourceFragment.Identifier, staticProperty.Name);

                var memberProperty = new CodeMemberProperty
                {
                    Name       = accessorName,
                    HasGet     = true,
                    HasSet     = false,
                    Attributes =
                        MemberAttributes.Public | MemberAttributes.Final,
                    Type = new CodeTypeReference(typeof(RelationCmd))
                };

                if (!string.IsNullOrEmpty(link.AccessorDescription))
                {
                    WXMLCodeDomGenerator.SetMemberDescription(memberProperty, link.AccessorDescription);
                }

                memberProperty.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodeMethodInvokeExpression(
                            new CodeThisReferenceExpression(),
                            "GetCmd",
                            new CodePropertyReferenceExpression(
                                new CodePropertyReferenceExpression(
                                    null, //WXMLCodeDomGeneratorHelper.GetEntityClassReferenceExpression(_settings, _entity, false),
                                    staticProperty.Name
                                    ),
                                "M2MRel"
                                )
                            )
                        )
                    );

                Members.Add(memberProperty);

                _gen.RaisePropertyCreated(null, this, memberProperty, null);
            }

            #endregion

            #region SelfRelation
            foreach (var relation in _entity.GetM2MSelfRelations(false))
            {
                var accessorName = relation.Direct.AccessorName;

                if (!string.IsNullOrEmpty(accessorName))
                {
                    var entityTypeExpression = Settings.UseTypeInProps ? WXMLCodeDomGeneratorHelper.GetEntityClassTypeReferenceExpression(_settings, _entity, false) : WXMLCodeDomGeneratorHelper.GetEntityNameReferenceExpression(_settings, _entity, false);

                    var desc = new CodeObjectCreateExpression(
                        new CodeTypeReference(typeof(M2MRelationDesc)),
                        entityTypeExpression);

                    accessorName = WXMLCodeDomGeneratorNameHelper.GetMultipleForm(accessorName);

                    var staticProperty = new CodeMemberProperty
                    {
                        Name       = accessorName + "Relation",
                        HasGet     = true,
                        HasSet     = false,
                        Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static,
                        Type       = relationDescType
                    };

                    staticProperty.GetStatements.Add(new CodeMethodReturnStatement(
                                                         new CodeObjectCreateExpression(typeof(RelationDescEx),
                                                                                        new CodeObjectCreateExpression(typeof(EntityUnion),
                                                                                                                       WXMLCodeDomGeneratorHelper.GetEntityNameReferenceExpression(_settings, _entity, false)
                                                                                                                       ), desc)
                                                         ));

                    GetRelationMethods(relation.SourceFragment.Identifier, staticProperty.Name);

                    //desc.Parameters.Add(new CodePrimitiveExpression(relation.Direct.FieldName));
                    //desc.Parameters.Add(new CodeFieldReferenceExpression(
                    //    new CodeTypeReferenceExpression(typeof(M2MRelationDesc)),"DirKey")
                    //);
                    desc.Parameters.Add(new CodePrimitiveExpression(relation.SourceFragment.Identifier));

                    Members.Add(staticProperty);

                    var memberProperty = new CodeMemberProperty
                    {
                        Name       = accessorName,
                        HasGet     = true,
                        HasSet     = false,
                        Attributes =
                            MemberAttributes.Public | MemberAttributes.Final,
                        Type = new CodeTypeReference(typeof(RelationCmd))
                    };

                    if (!string.IsNullOrEmpty(relation.Direct.AccessorDescription))
                    {
                        WXMLCodeDomGenerator.SetMemberDescription(memberProperty, relation.Direct.AccessorDescription);
                    }

                    memberProperty.GetStatements.Add(
                        new CodeMethodReturnStatement(
                            new CodeMethodInvokeExpression(
                                new CodeThisReferenceExpression(),
                                "GetCmd",
                                new CodePropertyReferenceExpression(
                                    new CodePropertyReferenceExpression(
                                        null, //WXMLCodeDomGeneratorHelper.GetEntityClassReferenceExpression(_settings, _entity, false),
                                        staticProperty.Name
                                        ),
                                    "M2MRel"
                                    )
                                )
                            )
                        );

                    Members.Add(memberProperty);

                    _gen.RaisePropertyCreated(null, this, memberProperty, null);
                }

                accessorName = relation.Reverse.AccessorName;

                if (!string.IsNullOrEmpty(accessorName))
                {
                    var entityTypeExpression = WXMLCodeDomGeneratorHelper.GetEntityNameReferenceExpression(_settings, _entity, false);
                    var desc = new CodeObjectCreateExpression(
                        new CodeTypeReference(typeof(M2MRelationDesc)),
                        entityTypeExpression);

                    accessorName = WXMLCodeDomGeneratorNameHelper.GetMultipleForm(accessorName);

                    var staticProperty = new CodeMemberProperty
                    {
                        Name       = accessorName + "Relation",
                        HasGet     = true,
                        HasSet     = false,
                        Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static,
                        Type       = relationDescType
                    };

                    staticProperty.GetStatements.Add(new CodeMethodReturnStatement(
                                                         new CodeObjectCreateExpression(typeof(RelationDescEx),
                                                                                        new CodeObjectCreateExpression(typeof(EntityUnion),
                                                                                                                       WXMLCodeDomGeneratorHelper.GetEntityNameReferenceExpression(_settings, _entity, false)
                                                                                                                       ), desc)
                                                         ));
                    //desc.Parameters.Add(new CodePrimitiveExpression(relation.Reverse.FieldName));
                    //desc.Parameters.Add(new CodeFieldReferenceExpression(
                    //    new CodeTypeReferenceExpression(typeof(M2MRelationDesc)),"RevKey")
                    //);
                    desc.Parameters.Add(new CodePrimitiveExpression(M2MRelationDesc.ReversePrefix + relation.SourceFragment.Identifier));

                    GetRelationMethods(relation.SourceFragment.Identifier, staticProperty.Name);

                    Members.Add(staticProperty);

                    var memberProperty = new CodeMemberProperty
                    {
                        Name       = accessorName,
                        HasGet     = true,
                        HasSet     = false,
                        Attributes =
                            MemberAttributes.Public | MemberAttributes.Final,
                        Type = new CodeTypeReference(typeof(RelationCmd))
                    };

                    if (!string.IsNullOrEmpty(relation.Reverse.AccessorDescription))
                    {
                        WXMLCodeDomGenerator.SetMemberDescription(memberProperty, relation.Reverse.AccessorDescription);
                    }

                    memberProperty.GetStatements.Add(
                        new CodeMethodReturnStatement(
                            new CodeMethodInvokeExpression(
                                new CodeThisReferenceExpression(),
                                "GetCmd",
                                new CodePropertyReferenceExpression(
                                    new CodePropertyReferenceExpression(
                                        null, //WXMLCodeDomGeneratorHelper.GetEntityClassReferenceExpression(_settings, _entity, false),
                                        staticProperty.Name
                                        ),
                                    "M2MRel"
                                    )
                                )
                            )
                        );

                    Members.Add(memberProperty);

                    _gen.RaisePropertyCreated(null, this, memberProperty, null);
                }
            }

            #endregion
        }
        protected virtual void OnPupulateEntityRelations()
        {
            var relationDescType = new CodeTypeReference(typeof(RelationDescEx));

            foreach (var entityRelation in _entity.GetActiveOne2ManyRelations())
            {
                string accessorName = string.IsNullOrEmpty(entityRelation.AccessorName) ? WXMLCodeDomGeneratorNameHelper.GetMultipleForm(entityRelation.Entity.Name) : entityRelation.AccessorName;

                var staticProperty = new CodeMemberProperty
                {
                    Name       = accessorName + "Relation",
                    HasGet     = true,
                    HasSet     = false,
                    Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static,
                    Type       = relationDescType
                };

                var entityTypeExpression     = Settings.UseTypeInProps ? WXMLCodeDomGeneratorHelper.GetEntityClassTypeReferenceExpression(_settings, entityRelation.Entity, entityRelation.Entity.Namespace != _entity.Namespace || _entity.ScopeNames().Any(item => item == entityRelation.Entity.Name)) : WXMLCodeDomGeneratorHelper.GetEntityNameReferenceExpression(_settings, entityRelation.Entity, entityRelation.Entity.Namespace != _entity.Namespace || _entity.ScopeNames().Any(item => item == entityRelation.Entity.Name));
                var selfEntityTypeExpression = Settings.UseTypeInProps ? WXMLCodeDomGeneratorHelper.GetEntityClassTypeReferenceExpression(_settings, _entity, false) : WXMLCodeDomGeneratorHelper.GetEntityNameReferenceExpression(_settings, _entity, false);

                staticProperty.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodeObjectCreateExpression(
                            relationDescType,
                            new CodeObjectCreateExpression(
                                typeof(EntityUnion),
                                selfEntityTypeExpression
                                ),
                            new CodeObjectCreateExpression(
                                typeof(RelationDesc),
                                new CodeObjectCreateExpression(
                                    new CodeTypeReference(typeof(EntityUnion)),
                                    entityTypeExpression
                                    ),
                                WXMLCodeDomGeneratorHelper.GetFieldNameReferenceExpression(_settings, entityRelation.Property, entityRelation.Entity.Namespace != _entity.Namespace || _entity.ScopeNames().Any(item => item == entityRelation.Entity.Name)),
                                new CodePrimitiveExpression(entityRelation.Name ?? "default")
                                )
                            )
                        )
                    );

                Members.Add(staticProperty);

                string cd = new WXMLCodeDomGeneratorNameHelper(_settings).GetEntityClassName(entityRelation.Property.Entity, entityRelation.Entity.Namespace != _entity.Namespace || _entity.ScopeNames().Any(item => item == entityRelation.Entity.Name)) + ".Properties";
                //string dn = new WXMLCodeDomGeneratorNameHelper(_settings).GetEntityClassName(entityRelation.Entity, true) + ".Descriptor";

                //CodeDom.Field<string>(CodeDom.TypeRef(dn), "EntityName")

                CodeExpression exp = CodeDom.GetExpression((EntityUnion hostEntity) =>
                                                           new RelationDescEx(hostEntity, new RelationDesc(
                                                                                  new EntityUnion(CodeDom.InjectExp <string>(0)),
                                                                                  CodeDom.Field <string>(CodeDom.TypeRef_str(cd), entityRelation.Property.PropertyAlias),
                                                                                  entityRelation.Name
                                                                                  )), entityTypeExpression);

                Members.Add(Define.Method(MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static,
                                          typeof(RelationDescEx),
                                          (EntityUnion hostEntity) => "Get" + staticProperty.Name,
                                          Emit.@return(exp)
                                          ));

                Members.Add(Define.Method(MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static,
                                          typeof(RelationDescEx),
                                          (EntityUnion hostEntity, EntityUnion joinEntity) => "Get" + staticProperty.Name,
                                          Emit.@return((EntityUnion hostEntity, EntityUnion joinEntity) =>
                                                       new RelationDescEx(hostEntity, new RelationDesc(
                                                                              joinEntity,
                                                                              CodeDom.Field <string>(CodeDom.TypeRef_str(cd), entityRelation.Property.PropertyAlias),
                                                                              entityRelation.Name
                                                                              ))
                                                       )
                                          ));

                var memberProperty = new CodeMemberProperty
                {
                    Name       = accessorName,
                    HasGet     = true,
                    HasSet     = false,
                    Attributes =
                        MemberAttributes.Public | MemberAttributes.Final,
                    Type = new CodeTypeReference(typeof(RelationCmd))
                };

                if (!string.IsNullOrEmpty(entityRelation.AccessorDescription))
                {
                    WXMLCodeDomGenerator.SetMemberDescription(memberProperty, entityRelation.AccessorDescription);
                }

                memberProperty.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodeMethodInvokeExpression(
                            new CodeThisReferenceExpression(),
                            "GetCmd",
                            new CodePropertyReferenceExpression(
                                new CodePropertyReferenceExpression(
                                    null, //WXMLCodeDomGeneratorHelper.GetEntityClassReferenceExpression(_settings, _entity, false),
                                    staticProperty.Name
                                    ),
                                "Rel"
                                )
                            )
                        )
                    );
                Members.Add(memberProperty);

                _gen.RaisePropertyCreated(null, this, memberProperty, null);
            }
        }
        private void ImplementIRelation(SelfRelationDefinition relation, EntityDefinition entity, CodeTypeDeclaration entitySchemaDefClass)
        {
            entitySchemaDefClass.BaseTypes.Add(new CodeTypeReference(typeof(IRelation)));

            #region Pair<string, Type> GetFirstType()
            CodeMemberMethod method = new CodeMemberMethod
            {
                Name = "GetFirstType",
                // тип возвращаемого значения
                ReturnType = new CodeTypeReference(typeof(IRelation.RelationDesc)),
                // модификаторы доступа
                Attributes = MemberAttributes.Public
            };
            // реализует метод базового класса
            method.ImplementationTypes.Add(typeof(IRelation));
            method.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeObjectCreateExpression(
                        new CodeTypeReference(typeof(IRelation.RelationDesc)),
                        WXMLCodeDomGeneratorHelper.GetFieldNameReferenceExpression(Settings,
                                                                                   entity.GetActiveProperties().OfType <EntityPropertyDefinition>().SingleOrDefault(item =>
                                                                                                                                                                    item.SourceFields.Any(sf => relation.Direct.FieldName.Contains(sf.SourceFieldExpression)))
                                                                                   , false),
                        new CodeMethodInvokeExpression(
                            new CodeMethodReferenceExpression(
                                new CodeFieldReferenceExpression(
                                    new CodeThisReferenceExpression(),
                                    "_schema"
                                    ),
                                "GetTypeByEntityName"
                                ),
                            new CodePrimitiveExpression(relation.Entity.Name)
                            ),
                        new CodePrimitiveExpression(true)
                        )
                    )
                );
            entitySchemaDefClass.Members.Add(method);
            #endregion Pair<string, Type> GetFirstType()

            #region Pair<string, Type> GetSecondType()
            method = new CodeMemberMethod
            {
                Name = "GetSecondType",
                // тип возвращаемого значения
                ReturnType = new CodeTypeReference(typeof(IRelation.RelationDesc)),
                // модификаторы доступа
                Attributes = MemberAttributes.Public
            };
            // реализует метод базового класса
            method.ImplementationTypes.Add(typeof(IRelation));
            method.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeObjectCreateExpression(
                        new CodeTypeReference(typeof(IRelation.RelationDesc)),
                        WXMLCodeDomGeneratorHelper.GetFieldNameReferenceExpression(Settings,
                                                                                   entity.GetActiveProperties().OfType <EntityPropertyDefinition>().SingleOrDefault(item =>
                                                                                                                                                                    item.SourceFields.Any(sf => relation.Reverse.FieldName.Contains(sf.SourceFieldExpression)))
                                                                                   , false),
                        new CodeMethodInvokeExpression(
                            new CodeMethodReferenceExpression(
                                new CodeFieldReferenceExpression(
                                    new CodeThisReferenceExpression(),
                                    "_schema"
                                    ),
                                "GetTypeByEntityName"
                                ),
                            new CodePrimitiveExpression(relation.Entity.Name)
                            ),
                        new CodePrimitiveExpression(false)
                        )
                    )
                );
            entitySchemaDefClass.Members.Add(method);
            #endregion Pair<string, Type> GetSecondType()
        }