public IndexUpdateGenerator(PropertyInfo prop)
 {
     this.prop      = prop;
     this.nullValue = IndexUtils.GetNullValue(prop);
 }
Exemplo n.º 2
0
        private static void GetIndexesForASingleGrainType(ApplicationPartsIndexableGrainLoader loader, IndexRegistry registry, Type grainClassType)
        {
            // First see if any indexed interfaces on this grain were already encountered on another grain (unless we're
            // in validation mode, which doesn't create the indexes).
            var indexedInterfacesAndProperties = EnumerateIndexedInterfacesForAGrainClassType(grainClassType).ToList();
            var indexedInterfaces = loader != null
                    ? new HashSet <Type>(indexedInterfacesAndProperties.Select(tup => tup.interfaceType).Where(itfType => registry.ContainsKey(itfType)))
                    : new HashSet <Type>();

            var grainIndexesAreEager = indexedInterfaces.Count > 0 ? registry[indexedInterfaces.First()].HasAnyEagerIndex : default(bool?);
            var consistencyScheme    = grainClassType.GetConsistencyScheme();

            // Now find all indexed interfaces we're seeing for the first time (again, unless we're in validation mode).
            foreach (var(grainInterfaceType, propertiesClassType) in indexedInterfacesAndProperties)
            {
                if (!indexedInterfaces.Contains(grainInterfaceType))
                {
                    grainIndexesAreEager = CreateIndexesForASingleInterface(loader, registry, propertiesClassType, grainInterfaceType,
                                                                            grainClassType, consistencyScheme, grainIndexesAreEager);
                    indexedInterfaces.Add(grainInterfaceType);
                }
            }

            IReadOnlyDictionary <string, object> getNullValuesDictionary()
            {
                IEnumerable <(string propName, (string itfName, object nullValue))> getNullPropertyValuesForInterface(Type interfaceType)
                => registry[interfaceType].PropertiesClassType.GetProperties()
                .Select(info => (name: info.Name, nullSpec: (itfname: interfaceType.Name, nullValue: IndexUtils.GetNullValue(info))))
                .Where(p => p.nullSpec.nullValue != null);

                Dictionary <string, (string, object)> addToDict(Dictionary <string, (string, object)> dict, (string propName, (string itfName, object nullValue)nullSpec) current)
                {
                    bool isInDict(string propName)
                    {
                        return(dict.TryGetValue(propName, out (string itfName, object nullValue)prevNullSpec)
                            ? (prevNullSpec.nullValue.Equals(current.nullSpec.nullValue)
                                ? true
                                : throw new IndexConfigurationException($"Property {propName} has conflicting NullValues defined on interfaces {prevNullSpec.itfName} and {current.nullSpec.itfName}"))
                            : false);
                    }

                    if (!isInDict(current.propName))
                    {
                        dict[current.propName] = current.nullSpec;
                    }
                    return(dict);
                }

                return(indexedInterfaces.SelectMany(itf => getNullPropertyValuesForInterface(itf))
                       .Aggregate(new Dictionary <string, (string itfName, object nullValue)>(), (dict, pair) => addToDict(dict, pair))
                       .ToDictionary(kvp => kvp.Key, kvp => kvp.Value.nullValue));
            }

            if (indexedInterfaces.Count > 0)
            {
                registry.SetGrainIndexes(grainClassType, indexedInterfaces.ToArray(), getNullValuesDictionary());
            }
        }
        private async static Task GetIndexesForASingleGrainType(ApplicationPartsIndexableGrainLoader loader, IndexRegistry registry, Type grainClassType)
        {
            if (!typeof(IIndexableGrain).IsAssignableFrom(grainClassType))
            {
                return;
            }

            if (registry.ContainsGrainType(grainClassType))
            {
                throw new InvalidOperationException($"Grain class type {grainClassType.Name} has already been added to the registry");
            }

            bool?grainIndexesAreEager = null;
            var  indexedInterfaces    = new List <Type>();
            var  consistencyScheme    = grainClassType.GetConsistencyScheme();

            foreach (var(grainInterfaceType, propertiesClassType) in EnumerateIndexedInterfacesForAGrainClassType(grainClassType).Where(tup => !registry.ContainsKey(tup.interfaceType)))
            {
                grainIndexesAreEager = await CreateIndexesForASingleInterface(loader, registry, propertiesClassType, grainInterfaceType,
                                                                              grainClassType, consistencyScheme, grainIndexesAreEager);

                indexedInterfaces.Add(grainInterfaceType);
            }

            IReadOnlyDictionary <string, object> getNullValuesDictionary()
            {
                IEnumerable <(string propName, (string itfName, object nullValue))> getNullPropertyValuesForInterface(Type interfaceType)
                => registry[interfaceType].PropertiesClassType.GetProperties()
                .Select(info => (name: info.Name, nullSpec: (itfname: interfaceType.Name, nullValue: IndexUtils.GetNullValue(info))))
                .Where(p => p.nullSpec.nullValue != null);

                Dictionary <string, (string, object)> addToDict(Dictionary <string, (string, object)> dict, (string propName, (string itfName, object nullValue)nullSpec) current)
                {
                    bool isInDict(string propName)
                    {
                        return(dict.TryGetValue(propName, out (string itfName, object nullValue)prevNullSpec)
                            ? (prevNullSpec.nullValue.Equals(current.nullSpec.nullValue)
                                ? true
                                : throw new IndexConfigurationException($"Property {propName} has conflicting NullValues defined on interfaces {prevNullSpec.itfName} and {current.nullSpec.itfName}"))
                            : false);
                    }

                    if (!isInDict(current.propName))
                    {
                        dict[current.propName] = current.nullSpec;
                    }
                    return(dict);
                }

                return(indexedInterfaces.SelectMany(itf => getNullPropertyValuesForInterface(itf))
                       .Aggregate(new Dictionary <string, (string itfName, object nullValue)>(), (dict, pair) => addToDict(dict, pair))
                       .ToDictionary(kvp => kvp.Key, kvp => kvp.Value.nullValue));
            }

            registry.SetGrainIndexes(grainClassType, indexedInterfaces.ToArray(), getNullValuesDictionary());
        }