internal static void ResolveReferences(IUnifiedIMObject obj, Type type = null)
 {
     if (type == null)
     {
         type = obj.GetType();
     }
     if (TypeReferences.ContainsKey(type))
     {
         foreach (UnifiedIMReference reference in TypeReferences[type])
         {
             ResolveReference(obj, reference, type);
         }
     }
 }
        internal static void RegisterType(Type type)
        {
            if (AllowReferences)
            {
                PropertyInfo[] props = type.GetPropertiesCached()
                                       .Union(type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance))
                                       .ToArray();
                foreach (PropertyInfo prop in props)
                {
                    UnifiedIMReference reff = prop.GetCustomAttribute <UnifiedIMReference>();
                    UnifiedIMIndex     indx = prop.GetCustomAttribute <UnifiedIMIndex>();
                    bool alreadyIndexed     = false;

                    if (reff != null)
                    {
                        if (reff.HostPropertyType == null)
                        {
                            reff.HostPropertyType = props.FirstOrDefault(x => x.Name == reff.HostProperty)?.PropertyType;
                        }
                        if (reff.HostType == null)
                        {
                            reff.HostType = prop.DeclaringType;
                        }
                        reff.SetProperty     = prop.Name;
                        reff.SetPropertyType = prop.PropertyType;
                        if (reff.SetPropertyType == null)
                        {
                            throw new ArgumentException("Set Property does not exist");
                        }
                        References.Add(reff);
                        if (!HostReferences.ContainsKey(type))
                        {
                            HostReferences.Add(type, new List <UnifiedIMReference>());
                        }
                        HostReferences[type].Add(reff);
                        if (!TargetReferences.ContainsKey(reff.TargetType))
                        {
                            TargetReferences.Add(reff.TargetType, new List <UnifiedIMReference>());
                        }
                        TargetReferences[reff.TargetType].Add(reff);
                        if (!TypeReferences.ContainsKey(reff.HostType))
                        {
                            TypeReferences.Add(reff.HostType, new List <UnifiedIMReference>());
                        }
                        if (!TypeReferences.ContainsKey(reff.TargetType))
                        {
                            TypeReferences.Add(reff.TargetType, new List <UnifiedIMReference>());
                        }
                        TypeReferences[reff.TargetType].Add(reff);
                        TypeReferences[reff.HostType].Add(reff);
                        if (AllowIndexes && CreateReferenceIndexes)
                        {
                            if (reff.TargetProperty != "ObjectID" && !HasIndex(reff.TargetType, reff.TargetProperty))
                            {
                                AddIndex(reff.TargetType, reff.TargetProperty);
                            }
                            if (reff.HostProperty != "ObjectID" && !HasIndex(reff.HostType, reff.HostProperty))
                            {
                                AddIndex(reff.HostType, reff.HostProperty);
                            }

                            if (reff.TargetType == type || reff.HostType == type)
                            {
                                alreadyIndexed = true;
                            }
                        }
                    }

                    if (!alreadyIndexed && prop.Name != "ObjectID" && indx != null)
                    {
                        AddIndex(type, prop.Name);
                    }
                }
            }

            if (!_databaseGetters.ContainsKey(type))
            {
                _databaseGetters.Add(type, ((IUnifiedIMObject)Activator.CreateInstance(type)).DatabaseBase);
            }
        }
        internal static void HandleObjectCreation <T>(IUnifiedIMObject obj)
        {
            if (UnifiedSystem.AllowReferences)
            {
                UnifiedSystem.ResolveReferences(obj, typeof(T));
            }
            if (UnifiedSystem.UseOmniBase)
            {
                lock (UnifiedSystem.OmniBase)
                    UnifiedSystem.OmniBase.Add(obj.ObjectID, obj);
            }

            List <string> indexesToAdd = new List <string>();

            if (UnifiedSystem.AllowReferences)
            {
                List <UnifiedIMReference> refs = new List <UnifiedIMReference>();
                if (TypeReferences.ContainsKey(typeof(T)))
                {
                    refs = TypeReferences[typeof(T)];
                }

                /*
                 * ObjectIndex<IUnifiedIMObject> oi = null;
                 * if (CreateReferenceIndexes)
                 *  if (Indexes.ContainsKey(typeof(T)))
                 *      oi = Indexes[typeof(T)];*/

                foreach (UnifiedIMReference reff in refs)
                {
                    if (reff.HostType == typeof(T))
                    {
                        //object value = reff.GetHostProperty(obj);
                        //if(!obj.PropertyStates.ContainsKey(reff.HostProperty))
                        //obj.PropertyStates.Add(reff.HostProperty, new UIMPropertyState(value));
                        if (CreateReferenceIndexes && reff.HostProperty != "ObjectID")
                        {
                            // oi.AddIndex(reff.HostProperty, value, obj);
                            indexesToAdd.Add(reff.HostProperty);
                        }
                    }

                    else if (reff.TargetType == typeof(T))
                    {
                        //object value = reff.GetTargetProperty(obj);
                        //if (!obj.PropertyStates.ContainsKey(reff.TargetProperty))
                        //    obj.PropertyStates.Add(reff.TargetProperty, new UIMPropertyState(value));
                        if (CreateReferenceIndexes && reff.TargetProperty != "ObjectID")
                        {
                            //oi.AddIndex(reff.TargetProperty, value, obj);
                            indexesToAdd.Add(reff.TargetProperty);
                        }
                    }
                }
            }

            if (AllowIndexes)
            {
                if (IndexProperties.ContainsKey(typeof(T)))
                {
                    indexesToAdd.AddRange(IndexProperties[typeof(T)]);
                }

                ObjectIndexer <IUnifiedIMObject> oi = null;
                if (Indexes.ContainsKey(typeof(T)))
                {
                    oi = Indexes[typeof(T)];
                }

                if (oi != null)
                {
                    foreach (string idx in indexesToAdd.Distinct())
                    {
                        object value = Property.Get(obj, idx);
                        if (!obj.PropertyStates.ContainsKey(idx))
                        {
                            obj.PropertyStates.Add(idx, new UIMPropertyState(value));
                        }
                        oi.AddIndex(idx, value, obj);
                    }
                }
            }
        }