private MetaType EnsureForMetaType(Type type)
        {
            if (metaTypes.TryGetValue(type.FullName, out MetaType metaType))
            {
                return(metaType);
            }
            if (type.IsGenericTypeDefinition || type.IsSignatureType || type.IsAbstract || type.IsPrimitive || type.IsArray)
            {
                return(null);
            }

            if (type.GetConstructors().FirstOrDefault(c => c.GetParameters().Length == 0) == null)
            {
                return(null);
            }

            var result = new MetaType(type, EnsureForMetaType);

            metaTypes[result.DescribedType.FullName] = result;
            KnownTypeAttributes.ApplyDiscoveredAttributes(result, type.GetCustomAttributes());
            foreach (var prop in result.MetaProperties.Values)
            {
                if (prop.DeclaredAt == result)
                {
                    KnownPropertyAttributes.ApplyDiscoveredAttributes(metaType, prop, prop.Member.GetCustomAttributes());
                }
            }
            result.PropertiesUpdated();
            return(result);
        }
        protected virtual void InitiaizePipelines()
        {
            KnownTypeAttributes.AddAttributeHandler <Persisted>((type, persisted) =>
            {
                type.MarkAsPersisted();
            });
            KnownTypeAttributes.AddAttributeHandler <IdPrefix>((metaType, idPrefix) =>
            {
                metaType.UseIdPrefix(idPrefix.Prefix);
            });
            KnownTypeAttributes.AddAttributeHandler <StoreName>((metaType, storeName) =>
            {
                metaType.BindToStoreName(storeName.Name);
            });

            KnownPropertyAttributes.AddAttributeHandler <Indexing>((type, prop, indexing) =>
            {
                prop.SetIndexingMode(indexing.Model);
                if (indexing.Model == IndexingModel.Keywords)
                {
                    type.EnableKeywordsSearch();
                }
            });
            KnownPropertyAttributes.AddAttributeHandler <NoIndexingAttribute>((type, prop, noIndexing) =>
            {
                prop.SetIndexingMode(IndexingModel.NoIndexing);
            });
            KnownPropertyAttributes.AddAttributeHandler <JSONOnlyAttribute>((type, prop, noIndexing) =>
            {
                prop.SetIndexingMode(IndexingModel.JSONOnly);
            });
            KnownPropertyAttributes.AddAttributeHandler <KeywordsAtribute>((type, prop, keywords) =>
            {
                prop.SetIndexingMode(IndexingModel.Keywords);
                type.EnableKeywordsSearch();
            });
            KnownPropertyAttributes.AddAttributeHandler <SearcheableAttribute>((type, prop, searcheable) =>
            {
                prop.SetIndexingMode(IndexingModel.Searcheable);
            });
            KnownPropertyAttributes.AddAttributeHandler <DefaultValue>((type, prop, defaultValue) =>
            {
                prop.SetDefaultValue(defaultValue.ValueType, defaultValue.Value);
            });
            KnownPropertyAttributes.AddAttributeHandler <Required>((type, prop, req) =>
            {
                prop.MakeRequired();
                prop.AddValidatorImplementation(req);
            });
            KnownPropertyAttributes.AddAttributeHandler <InRangeAttribute>((type, prop, range) =>
            {
                prop.RestrictToRange(range.Min, range.Max);
                prop.AddValidatorImplementation(range);
            });
            KnownPropertyAttributes.AddAttributeHandler <InListAttribute>((type, prop, listAttr) =>
            {
                prop.RestrictToList(listAttr.Values);
                prop.AddValidatorImplementation(listAttr);
            });
            KnownPropertyAttributes.AddAttributeHandler <EntityKeyAttribute>((metaType, prop, keyAttr) =>
            {
                prop.UseAsEntityKey(keyAttr.KeyType);
            });
        }