// TODO: Will need lots of validation in the actual implementation public object Deserialize(Type stateType, GrainReference grainReference, GrainStateEntity[] stateValues) { var result = Activator.CreateInstance(stateType); // 2. Loop through all GrainStatEntities and assign them as properties foreach (var entity in stateValues) { if (entity.Id.Contains(".")) { // 2.1 If the property name contains a dot, this is a key-value collection var nameParts = entity.Id.Split('.'); var property = stateType.GetProperty(nameParts[0]); var collection = property.GetValue(result); // If the property is null, create a new instance if (collection == null) { collection = Activator.CreateInstance(property.PropertyType); property.SetValue(result, collection); } // Deserialise the state var typeofT = property.PropertyType.GetGenericArguments()[1]; var value = JsonConvert.DeserializeObject(entity.State.ToString(), typeofT, _options.JsonSerializerSettings); // Determine the dictionary Key var key = string.Join(".", nameParts.Skip(1)); // Add the value to the collection var dictionary = (IDictionary)collection; dictionary.Add(key, value); } else { // 2.2 If the property name doesn't contain a dot, it's a top-level value var property = stateType.GetProperty(entity.Id); if (property != null /* TODO: Ensure property should be read */) { var value = JsonConvert.DeserializeObject(entity.State.ToString(), property.PropertyType, _options.JsonSerializerSettings); property.SetValue(result, value); } } // Store the hash of the value in the StateCache var cacheKey = GetCacheKey(grainReference, entity.Id); var hash = _hasher.CalculateHash(entity.State.ToString()); StateCache[cacheKey] = hash; } // 3. Return the result return(result); }