예제 #1
0
        public static void EntitiesContextInitialization <T>() where T : EntitiesContext
        {
            if (_contexts.Value.FirstOrDefault(c => c.Name == (typeof(T).Name)).IsNull())
            {
                string sessionid = MVCEngine.Tools.Session.Session.CreateUserSession(typeof(T).Name);
                Task   task      = new Task(() =>
                {
                    Dictionary <MVCEngine.Model.Internal.Descriptions.DynamicProperties, string[]> dynamicList =
                        new Dictionary <MVCEngine.Model.Internal.Descriptions.DynamicProperties, string[]>();
                    Context ctx = new Context()
                    {
                        Name    = typeof(T).Name,
                        Entites = new List <EntityClass>()
                    };
                    _contexts.Value.Add(ctx);
                    _entitiesCollection.Value.Add(ctx.Name, new Dictionary <string, Func <object, object> >());

                    typeof(T).GetFields().Where(f => f.FieldType.Name == "EntitiesCollection`1" && f.IsPublic).
                    ToList().ForEach((f) =>
                    {
                        List <string> realTimeValidator = new List <string>();
                        PropertyInfo ctxInfo            = f.FieldType.GetProperty("Context");
                        Type entityType = f.FieldType.GetGenericArguments().First <Type>();
                        Debug.Assert(typeof(Entity).IsAssignableFrom(entityType), "Entity[" + entityType.FullName + "] it cann't be recognise as valid entity.");
                        if (typeof(Entity).IsAssignableFrom(entityType))
                        {
                            if (!_entites.Value.ContainsKey(entityType.FullName))
                            {
                                EntityClass entityClass = new EntityClass();
                                Debug.Assert(!ctx.Entites.Exists((t) => { return(t.Name == entityType.Name); }), "Entity[" + entityType.Name + "] is defined twice.");
                                if (!ctx.Entites.Exists((t) => { return(t.Name == entityType.Name); }))
                                {
                                    entityClass.Name       = entityType.Name;
                                    entityClass.EntityType = entityType;
                                    entityClass.Attributes.AddRange(Attribute.GetCustomAttributes(entityType));

                                    _entitiesCollection.Value[ctx.Name].Add(entityType.Name, LambdaTools.FieldGetter(typeof(T), f));

                                    var propertyquery = entityType.GetProperties().Where(p => p.CanRead && p.GetGetMethod().IsVirtual);
                                    propertyquery.ToList().ForEach((p) =>
                                    {
                                        EntityProperty property = new EntityProperty()
                                        {
                                            Name         = p.Name,
                                            PropertyType = p.PropertyType,
                                            PropertyInfo = p,
                                            Setter       = p.CanWrite ? LambdaTools.PropertySetter(entityType, p) : null,
                                            Getter       = LambdaTools.PropertyGetter(entityType, p)
                                        };
                                        property.Attibutes.AddRange(Attribute.GetCustomAttributes(p));
                                        entityClass.Properties.Add(property);

                                        if (typeof(Entity).IsAssignableFrom(p.PropertyType))
                                        {
                                            property.ReletedEntity = new ReletedEntity()
                                            {
                                                Related           = Releted.Entity,
                                                RelatedEntityName = p.PropertyType.Name
                                            };
                                        }
                                        else if (p.PropertyType.Name == "EntitiesCollection`1")
                                        {
                                            property.ReletedEntity = new ReletedEntity()
                                            {
                                                Related           = Releted.List,
                                                RelatedEntityName = p.PropertyType.GetGenericArguments().First <Type>().Name
                                            };
                                        }
                                        Attribute.GetCustomAttributes(p).ToList().ForEach((a) =>
                                        {
                                            Relation relation           = null;
                                            Discriminator discriminator = null;
                                            PropertyValidator validator = null;
                                            DefaultValue defaultValue   = null;
                                            Synchronized synchronized   = null;
                                            Formatter formatter         = null;
                                            NotIntercept notIntercept   = null;
                                            Intercept intercept         = null;
                                            attribute.DynamicProperties dynamicProperties = null;
                                            if (a.IsTypeOf <PrimaryKey>())
                                            {
                                                Debug.Assert(entityClass.Properties.FirstOrDefault(primary => primary.PrimaryKey).IsNull(), "Entity[" + entityType.Name + "] at least two primary key property defined");
                                                property.PrimaryKey            = true;
                                                entityClass.PrimaryKeyProperty = property;
                                                entityClass.PrimaryKey         = property.Getter;
                                            }
                                            else if ((relation = a.CastToType <Relation>()).IsNotNull())
                                            {
                                                EntitiesRelation r = ctx.Relations.FirstOrDefault(re => re.Name == relation.RelationName);
                                                Debug.Assert(r.IsNull(), "Relation[" + relation.RelationName + "] is declared at least twice");
                                                if (property.ReletedEntity.IsNotNull())
                                                {
                                                    EntitiesRelation entityrelation = new EntitiesRelation()
                                                    {
                                                        Name   = relation.RelationName,
                                                        Parent = new EntityRelated()
                                                        {
                                                            EntityName = relation.ParentEntity,
                                                            Key        = relation.ParentProperty
                                                        },
                                                        Child = new EntityRelated()
                                                        {
                                                            EntityName = relation.ChildEntity,
                                                            Key        = relation.ChildProperty
                                                        },
                                                        OnDelete = relation.OnDelete,
                                                        OnAccept = relation.OnAccept,
                                                        OnFreeze = relation.OnFreeze
                                                    };
                                                    ctx.Relations.Add(entityrelation);
                                                    property.ReletedEntity.Relation = entityrelation;
                                                }
                                            }
                                            else if ((synchronized = a.CastToType <Synchronized>()).IsNotNull())
                                            {
                                                if (property.ReletedEntity.IsNotNull())
                                                {
                                                    property.ReletedEntity.Synchronized = true;
                                                }
                                            }
                                            else if ((discriminator = a.CastToType <Discriminator>()).IsNotNull())
                                            {
                                                if (property.ReletedEntity.IsNotNull())
                                                {
                                                    property.ReletedEntity.Discriminators.Add(discriminator);
                                                }
                                            }
                                            else if ((validator = a.CastToType <PropertyValidator>()).IsNotNull())
                                            {
                                                property.Validators.Add(validator);
                                            }
                                            else if ((defaultValue = a.CastToType <DefaultValue>()).IsNotNull())
                                            {
                                                property.DefaultValue = defaultValue;
                                            }
                                            else if ((dynamicProperties = a.CastToType <attribute.DynamicProperties>()).IsNotNull())
                                            {
                                                if (property.ReletedEntity.IsNotNull() && property.ReletedEntity.Related == Releted.List)
                                                {
                                                    entityClass.DynamicProperties = new Internal.Descriptions.DynamicProperties()
                                                    {
                                                        CodeProperty = dynamicProperties.CodeProperty,
                                                        Property     = property,
                                                    };
                                                    dynamicList.Add(entityClass.DynamicProperties, dynamicProperties.ValueProperties);
                                                }
                                            }
                                            else if ((formatter = a.CastToType <Formatter>()).IsNotNull())
                                            {
                                                property.AddFormatter(formatter);
                                            }
                                            else if ((notIntercept = a.CastToType <NotIntercept>()).IsNotNull())
                                            {
                                                if (notIntercept.InterceptorId.IsNullOrEmpty())
                                                {
                                                    property.RemoveGetInterceptor(string.Empty);
                                                    property.RemoveSetInterceptor(string.Empty);
                                                }
                                                else
                                                {
                                                    if (notIntercept.Method == Method.Get)
                                                    {
                                                        property.RemoveGetInterceptor(notIntercept.InterceptorId);
                                                    }
                                                    else
                                                    {
                                                        property.RemoveSetInterceptor(notIntercept.InterceptorId);
                                                    }
                                                }
                                            }
                                            else if ((intercept = a.CastToType <Intercept>()).IsNotNull() && intercept.Method.IsNotNull())
                                            {
                                                if (intercept.Method.Contains(Method.Get))
                                                {
                                                    property.AddGetInterceptor(intercept.InterceptorId);
                                                }

                                                if (intercept.Method.Contains(Method.Set))
                                                {
                                                    property.AddSetInterceptor(intercept.InterceptorId);
                                                }
                                            }
                                        });
                                    });
                                    Attribute.GetCustomAttributes(entityType).ToList().ForEach((a) =>
                                    {
                                        EntityValidator validator = null;
                                        if ((validator = a.CastToType <EntityValidator>()).IsNotNull())
                                        {
                                            entityClass.Validators.Add(validator);
                                        }
                                    });
                                    ctx.Entites.Add(entityClass);
                                }
                                _entites.Value.Add(entityType.FullName, entityClass);
                            }
                            else
                            {
                                ctx.Entites.Add(_entites.Value[entityType.FullName]);
                            }
                        }
                    });
                    ctx.Relations.ForEach((r) =>
                    {
                        EntityClass entity = ctx.Entites.FirstOrDefault(e => e.Name == r.Parent.EntityName);
                        Debug.Assert(entity.IsNotNull(), "Relation[" + r.Name + "] parent entity not found");
                        r.Parent.Entity         = entity;
                        EntityProperty property = entity.Properties.FirstOrDefault(p => p.Name == r.Parent.Key);
                        Debug.Assert(property.IsNotNull(), "Entity[" + entity.Name + "] property[" + r.Parent.Key + "] not defined");
                        r.Parent.Type  = property.PropertyType;
                        r.Parent.Value = property.Getter;

                        EntityClass childEntity = ctx.Entites.FirstOrDefault(e => e.Name == r.Child.EntityName);
                        Debug.Assert(childEntity.IsNotNull(), "Relation[" + r.Name + "] child entity not found");
                        r.Child.Entity = childEntity;
                        EntityProperty childProperty = childEntity.Properties.FirstOrDefault(p => p.Name == r.Child.Key);
                        Debug.Assert(childProperty.IsNotNull(), "Entity[" + childEntity.Name + "] property[" + r.Child.Key + "] not defined");
                        r.Child.Type  = childProperty.PropertyType;
                        r.Child.Value = childProperty.Getter;
                    });

                    var reletedquery = ctx.Entites.Where(e => e.Properties.Count(p => p.ReletedEntity.IsNotNull()) > 0).
                                       SelectMany(e => e.Properties.Where(p => p.ReletedEntity.IsNotNull()), (e, p) => new { Entity = e, Property = p });

                    reletedquery.ToList().ForEach((ep) =>
                    {
                        EntityClass entityClass = ctx.Entites.FirstOrDefault(e => e.Name == ep.Property.ReletedEntity.RelatedEntityName);
                        Debug.Assert(entityClass.IsNotNull(), "Entity[" + ep.Property.ReletedEntity.RelatedEntityName + "] dosen't have collection");
                        ep.Property.ReletedEntity.RelatedEntity = entityClass;
                        if (ep.Property.ReletedEntity.Relation.IsNull())
                        {
                            if (!ep.Property.ReletedEntity.RelationName.IsNullOrEmpty())
                            {
                                EntitiesRelation relation = ctx.Relations.FirstOrDefault(r => r.Name == ep.Property.ReletedEntity.RelationName);
                                Debug.Assert(relation.IsNotNull(), "Relation[" + ep.Property.ReletedEntity.RelationName + "] not defined");
                                ep.Property.ReletedEntity.Relation = relation;
                            }
                            else
                            {
                                List <EntitiesRelation> relations = null;
                                if (ep.Property.ReletedEntity.Related == Releted.Entity)
                                {
                                    relations = ctx.Relations.Where(r => r.Parent.EntityName == ep.Property.ReletedEntity.RelatedEntityName && r.Child.EntityName == ep.Entity.Name).ToList();
                                }
                                else
                                {
                                    relations = ctx.Relations.Where(r => r.Parent.EntityName == ep.Entity.Name && r.Child.EntityName == ep.Property.ReletedEntity.RelatedEntityName).ToList();
                                }

                                Debug.Assert(relations.Count() < 2, "Relation[" + ep.Property.ReletedEntity.RelatedEntityName + "-" + ep.Entity.Name + "] more then one");
                                if (relations.Count() == 1)
                                {
                                    ep.Property.ReletedEntity.Relation = relations[0];
                                }
                            }
                        }
                        if (ep.Property.ReletedEntity.Synchronized)
                        {
                            ep.Property.ReletedEntity.RelatedEntity.Synchronized(ep.Entity.Name, ep.Property.Name);
                        }
                        if (ep.Property.ReletedEntity.Related == Releted.List)
                        {
                            ep.Property.AddGetInterceptor(CollectionInterceptorDispatcher.GetId(ep.Property.ReletedEntity.Relation.Child.Entity.EntityType));
                        }
                        else
                        {
                            ep.Property.AddGetInterceptor(EntityInterceptorDispatcher.GetId(ep.Property.ReletedEntity.RelatedEntityName));
                        }
                    });

                    foreach (MVCEngine.Model.Internal.Descriptions.DynamicProperties dynamicProperty in dynamicList.Keys)
                    {
                        foreach (string p in dynamicList[dynamicProperty])
                        {
                            EntityProperty property = dynamicProperty.Property.ReletedEntity.RelatedEntity.Properties.FirstOrDefault(pr => pr.Name == p);
                            if (property.IsNotNull())
                            {
                                dynamicProperty.ValuesProperties.Add(property.PropertyType, property.Name);
                            }
                        }
                    }
                });

                task.ContinueWith((antecedent) =>
                {
                    MVCEngine.Tools.Session.Session.ReleaseSession(sessionid);
                });

                task.ContinueWith((antecedent) =>
                {
                    if (_contexts.IsValueCreated)
                    {
                        _contexts.Value.Clear();
                    }
                    //ToDo log exception into log file
                }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);

                MVCEngine.Tools.Session.Session.SetSessionData(sessionid, "InitializeTask", task);

                task.Start();
            }
        }