// Generates an expression that creates an NbtTag for given property of a directly-mappable types. // Directly-mappable types are: primitives, enums, byte[], int[], and string. public override Expression HandleDirectlyMappedType(string tagName, PropertyInfo property, NullPolicy selfPolicy) { // declare a local var, which will hold the property's value ParameterExpression varValue = Expression.Parameter(property.PropertyType); // Fallback path, in case value is null and NullPolicy is InsertDefaults Expression defaultVal = Expression.Constant(SerializationUtil.GetDefaultValue(property.PropertyType)); // varRootTag.Add( new NbtTag(tagName, <defaultVal>) ); Expression defaultValExpr = Expression.Call(varRootTag, NbtCompoundAddMethod, MakeNbtTagCtor(property.PropertyType, Expression.Constant(tagName, typeof(string)), defaultVal)); // varRootTag.Add( new NbtTag(tagName, <varValue>) ); Expression makeTagExpr = Expression.Call(varRootTag, NbtCompoundAddMethod, MakeNbtTagCtor(property.PropertyType, Expression.Constant(tagName, typeof(string)), varValue)); // Getter for the property value Expression getPropertyExpr = Expression.MakeMemberAccess(argValue, property); // generate the appropriate enclosing expressions, depending on NullPolicy return NbtCompiler.MakeNullHandler(varValue, getPropertyExpr, selfPolicy, makeTagExpr, defaultValExpr, MakePropertyNullMessage(property)); }
public override Expression HandleCompoundObject(string tagName, PropertyInfo property, NullPolicy selfPolicy) { return MakeNbtTagPropertyHandler( property, tagName, typeof(NbtCompound), selfPolicy, expr => callResolver.MakeCall(property.PropertyType, Expression.Constant(tagName, typeof(string)), expr)); }
Expression MakeNbtTagHandler([NotNull] Type tagType, [NotNull] Type valueType, [NotNull] Expression tagNameExpr, [NotNull] Expression getPropertyExpr, NullPolicy selfPolicy, [NotNull] String nullMsg, [NotNull] Func <ParameterExpression, Expression> conversionFunc, [NotNull] Func <Expression, Expression> processTagExpr) { // declare a local var, which will hold the property's value ParameterExpression varValue = Expression.Parameter(valueType, "value"); // Primary path, adds the root tag of the NbtFile Expression makeTagExpr = processTagExpr(conversionFunc(varValue)); // Fallback path, in case value is null and NullPolicy is InsertDefaults ConstructorInfo tagCtor; if (tagType == typeof(NbtTag)) { tagCtor = NbtCompoundCtor; } else { tagCtor = tagType.GetConstructor(new[] { typeof(string) }); } Expression defaultVal = Expression.New(tagCtor, tagNameExpr); Expression defaultValExpr = processTagExpr(defaultVal); // Generate the appropriate enclosing expressions, which choose path depending on NullPolicy return(NbtCompiler.MakeNullHandler(varValue, getPropertyExpr, selfPolicy, makeTagExpr, defaultValExpr, nullMsg)); }
public SwarmBenchmark() { _policy = new NullPolicy <DumbAction>(); _blocks = new List <Block <DumbAction> > { TestUtils.MineGenesis <DumbAction>(), }; _blocks.Add(TestUtils.MineNext(_blocks[0])); _blocks.Add(TestUtils.MineNext(_blocks[1])); _blocks.Add(TestUtils.MineNext(_blocks[2])); _blocks.Add(TestUtils.MineNext(_blocks[3])); }
public override Expression HandleStringIDictionary(string tagName, PropertyInfo property, Type iDictImpl, NullPolicy selfPolicy, NullPolicy elementPolicy) { Expression getIDictExpr = Expression.MakeMemberAccess(argValue, property); string nullElementMessage = MakeElementNullMessage(property); string nullMessage = MakePropertyNullMessage(property); return(MakeStringIDictionaryHandler( Expression.Constant(tagName, typeof(string)), getIDictExpr, iDictImpl, selfPolicy, elementPolicy, nullMessage, nullElementMessage, expr => Expression.Call(varRootTag, NbtCompoundAddMethod, expr))); }
public SwarmBenchmark() { _policy = new NullPolicy <DumbAction>(); _blocks = new List <Block <DumbAction> > { TestUtils.MineGenesis <DumbAction>(), }; _appProtocolVersion = AppProtocolVersion.Sign(new PrivateKey(), 1); _blocks.Add(TestUtils.MineNext(_blocks[0])); _blocks.Add(TestUtils.MineNext(_blocks[1])); _blocks.Add(TestUtils.MineNext(_blocks[2])); _blocks.Add(TestUtils.MineNext(_blocks[3])); }
Expression MakeNbtTagPropertyHandler([NotNull] PropertyInfo property, [NotNull] string tagName, [NotNull] Type tagType, NullPolicy selfPolicy, [NotNull] Func <ParameterExpression, Expression> conversionFunc) { // Getter for the property value Expression getPropertyExpr = Expression.MakeMemberAccess(argValue, property); string nullMsg = MakePropertyNullMessage(property); Expression tagNameExpr = Expression.Constant(tagName, typeof(string)); // Generate the appropriate enclosing expressions, which choose path depending on NullPolicy return(MakeNbtTagHandler(tagType, property.PropertyType, tagNameExpr, getPropertyExpr, selfPolicy, nullMsg, conversionFunc, tagExpr => Expression.Call(varRootTag, NbtCompoundAddMethod, tagExpr))); }
public SwarmBenchmark() { _policy = new NullPolicy <DumbAction>(); _stagePolicy = new VolatileStagePolicy <DumbAction>(); _miner = TestUtils.ChainPrivateKey; _blocks = new List <Block <DumbAction> > { TestUtils.MineGenesisBlock <DumbAction>(_policy.GetHashAlgorithm, _miner), }; _appProtocolVersion = AppProtocolVersion.Sign(new PrivateKey(), 1); _blocks.Add(TestUtils.MineNextBlock(_blocks[0], _policy.GetHashAlgorithm, _miner)); _blocks.Add(TestUtils.MineNextBlock(_blocks[1], _policy.GetHashAlgorithm, _miner)); _blocks.Add(TestUtils.MineNextBlock(_blocks[2], _policy.GetHashAlgorithm, _miner)); _blocks.Add(TestUtils.MineNextBlock(_blocks[3], _policy.GetHashAlgorithm, _miner)); }
internal static Expression MakeNullHandler([NotNull] ParameterExpression varValue, [NotNull] Expression getPropertyExpr, NullPolicy policy, [NotNull] Expression nonNullExpr, [NotNull] Expression defaultValExpr, [NotNull] string exceptionMessage) { // locate the getter for this property Expression ifExpr; switch (policy) { case NullPolicy.Error: ifExpr = Expression.IfThenElse( // if (value==null) throw new NullReferenceException(exceptionMessage) Expression.ReferenceEqual(varValue, Expression.Constant(null)), Expression.Throw( Expression.New(NullReferenceExceptionCtor, Expression.Constant(exceptionMessage))), // else <nonNullExpr> nonNullExpr); break; case NullPolicy.Ignore: ifExpr = Expression.IfThen( // if (value!=null) <nonNullExpr> Expression.Not(Expression.ReferenceEqual(varValue, Expression.Constant(null))), nonNullExpr); break; case NullPolicy.InsertDefault: ifExpr = Expression.IfThenElse( // if (value==null) <defaultValExpr> Expression.ReferenceEqual(varValue, Expression.Constant(null)), defaultValExpr, // else <nonNullExpr> nonNullExpr); break; default: throw new ArgumentOutOfRangeException("Unrecognized value for NullPolicy: " + policy); } return(Expression.Block( // var varValue = value.ThisProperty; new[] { varValue }, Expression.Assign(varValue, getPropertyExpr), // (check if value is null, and do something) ifExpr)); }
public override Expression HandleIList(string tagName, PropertyInfo property, Type iListImpl, NullPolicy selfPolicy, NullPolicy elementPolicy) { // Getter for the property value Expression getPropertyExpr = Expression.MakeMemberAccess(argValue, property); // Find the element type (the 'T' in IList<T>) Type elementType = iListImpl.GetGenericArguments()[0]; Expression tagNameExpr = Expression.Constant(tagName, typeof(string)); string selfNullMsg = MakePropertyNullMessage(property); string elementNullMsg = MakeElementNullMessage(property); return(MakeIListHandler(getPropertyExpr, elementType, tagNameExpr, selfPolicy, elementPolicy, selfNullMsg, elementNullMsg, expr => Expression.Call(varRootTag, NbtCompoundAddMethod, expr))); }
public async Task Copy() { using (StoreFixture fx = FxConstructor()) using (StoreFixture fx2 = FxConstructor()) { IStore s1 = fx.Store, s2 = fx2.Store; var policy = new NullPolicy <DumbAction>(); var blocks = new BlockChain <DumbAction>( policy, new VolatileStagePolicy <DumbAction>(), s1, fx.StateStore, MineGenesis <DumbAction>(policy.GetHashAlgorithm, GenesisMiner.PublicKey) .Evaluate(GenesisMiner, policy.BlockAction, fx.StateStore) ); // FIXME: Need to add more complex blocks/transactions. var key = new PrivateKey(); await blocks.MineBlock(key); await blocks.MineBlock(key); await blocks.MineBlock(key); s1.Copy(to: Fx.Store); Fx.Store.Copy(to: s2); Assert.Equal(s1.ListChainIds().ToHashSet(), s2.ListChainIds().ToHashSet()); Assert.Equal(s1.GetCanonicalChainId(), s2.GetCanonicalChainId()); foreach (Guid chainId in s1.ListChainIds()) { Assert.Equal(s1.IterateIndexes(chainId), s2.IterateIndexes(chainId)); foreach (BlockHash blockHash in s1.IterateIndexes(chainId)) { Assert.Equal( s1.GetBlock <DumbAction>(fx.GetHashAlgorithm, blockHash), s2.GetBlock <DumbAction>(fx2.GetHashAlgorithm, blockHash) ); } } // ArgumentException is thrown if the destination store is not empty. Assert.Throws <ArgumentException>(() => Fx.Store.Copy(fx2.Store)); } }
NbtTag HandleDirectlyMappedType([CanBeNull] string tagName, [CanBeNull] object value, [NotNull] PropertyInfo pinfo, NullPolicy nullPolicy, [NotNull] Type propType) { if (propType == null) { throw new ArgumentNullException("propType"); } if (value == null) { switch (nullPolicy) { case NullPolicy.InsertDefault: value = SerializationUtil.GetDefaultValue(propType); break; case NullPolicy.Ignore: return(null); default: // Default and Error throw MakeNullException(pinfo); } } if (propType == typeof(string)) { return(new NbtString(tagName, (string)value)); } else if (propType == typeof(byte[])) { return(new NbtByteArray(tagName, (byte[])value)); } else if (propType == typeof(int[])) { return(new NbtIntArray(tagName, (int[])value)); } else { throw new ArgumentException("Invalid property valueType given to DynamicConverter.HandleDirectlyMappedType: expected string, byte[], or int[]"); } }
NbtTag HandleIListInner <T>([CanBeNull] string tagName, PropertyInfo pinfo, List <T> value) { Type elementType = typeof(T); if (value == null) { NullPolicy np = GetNullPolicy(pinfo); switch (np) { case NullPolicy.Ignore: return(null); case NullPolicy.InsertDefault: return(MakeEmptyList(tagName, elementType)); default: throw MakeNullException(pinfo); } } // Get list length int count = value.Count; if (count == 0) { return(MakeEmptyList(tagName, elementType)); } NullPolicy elementNullPolicy = GetElementNullPolicy(pinfo); NbtList newList = new NbtList(tagName); foreach (T element in value) { newList.Add(HandleElement(null, element, elementNullPolicy)); } return(newList); }
NbtTag HandleArray([CanBeNull] string tagName, [CanBeNull] Array value, [NotNull] PropertyInfo pinfo) { if (pinfo == null) { throw new ArgumentNullException("pinfo"); } if (value == null) { NullPolicy np = GetNullPolicy(pinfo); switch (np) { case NullPolicy.Ignore: return(null); case NullPolicy.InsertDefault: return(MakeEmptyList(tagName, pinfo.PropertyType.GetElementType())); default: throw MakeNullException(pinfo); } } if (value.Length == 0) { return(MakeEmptyList(tagName, pinfo.PropertyType.GetElementType())); } NullPolicy elementNullPolicy = GetElementNullPolicy(pinfo); NbtList newList = new NbtList(tagName); for (int i = 0; i < value.Length; i++) { newList.Add(HandleElement(null, value.GetValue(i), elementNullPolicy)); } return(newList); }
NbtTag HandleNbtConvertible <T>([CanBeNull] string tagName, [CanBeNull] T value, [NotNull] PropertyInfo pinfo, Func <string, T, NbtTag> conversionFunc, Func <string, NbtTag> defaultValueFunc) { if (pinfo == null) { throw new ArgumentNullException("pinfo"); } if (value == null) { NullPolicy np = GetNullPolicy(pinfo); switch (np) { case NullPolicy.InsertDefault: return(defaultValueFunc(tagName)); case NullPolicy.Ignore: return(null); default: // Default and Error throw MakeNullException(pinfo); } } return(conversionFunc(tagName, value)); }
public abstract Expression HandleStringIDictionary([NotNull] string tagName, [NotNull] PropertyInfo property, [NotNull] Type iDictImpl, NullPolicy selfPolicy, NullPolicy elementPolicy);
public abstract Expression HandleNbtFile([NotNull] string tagName, [NotNull] PropertyInfo property, NullPolicy selfPolicy);
public NbtTag Serialize(object value, string tagName, bool skipInterfaceCheck = false, NullPolicy thisNullPolicy = NullPolicy.Error, NullPolicy elementNullPolicy = NullPolicy.Error) { if (value == null) { return new NbtCompound(tagName); } Type realType = value.GetType(); if (realType.IsPrimitive) { return SerializePrimitiveType(tagName, value); } var valueAsString = value as string; if (valueAsString != null) { return new NbtString(tagName, valueAsString); } // Serialize arrays var valueAsArray = value as Array; if (valueAsArray != null) { var valueAsByteArray = value as byte[]; if (valueAsByteArray != null) { return new NbtByteArray(tagName, valueAsByteArray); } var valueAsIntArray = value as int[]; if (valueAsIntArray != null) { return new NbtIntArray(tagName, valueAsIntArray); } Type elementType = realType.GetElementType(); return SerializeList(tagName, valueAsArray, elementType, elementNullPolicy); } if (!skipInterfaceCheck && value is INbtSerializable) { return ((INbtSerializable)value).Serialize(tagName); } // Serialize ILists if (realType.IsGenericType && realType.GetGenericTypeDefinition() == typeof(List<>)) { Type listType = realType.GetGenericArguments()[0]; return SerializeList(tagName, (IList)value, listType, elementNullPolicy); } // Skip serializing NbtTags and NbtFiles var valueAsTag = value as NbtTag; if (valueAsTag != null) { return valueAsTag; } var file = value as NbtFile; if (file != null) { return file.RootTag; } // Fallback for compound tags var compound = new NbtCompound(tagName); if (!propertyInfoRead) ReadPropertyInfo(); foreach (PropertyInfo property in properties) { if (!property.CanRead) continue; Type propType = property.PropertyType; object propValue = property.GetValue(value, null); // Handle null property values if (propValue == null) { NullPolicy selfNullPolicy = GetElementPolicy(property); switch (selfNullPolicy) { case NullPolicy.Ignore: continue; case NullPolicy.Error: throw new NullReferenceException("Null values not allowed for property " + property.Name); case NullPolicy.InsertDefault: propValue = SerializationUtil.GetDefaultValue(propType); break; } } string propTagName = propertyTagNames[property]; NbtTag tag; if (propType.IsPrimitive) { tag = SerializePrimitiveType(propTagName, propValue); } else if (propType.IsArray || propType == typeof(string)) { tag = Serialize(propValue, propTagName); } else { var innerSerializer = new NbtSerializer(property.PropertyType); tag = innerSerializer.Serialize(propValue, propTagName); } compound.Add(tag); } return compound; }
public override Expression HandleDirectlyMappedType(string tagName, PropertyInfo property, NullPolicy selfPolicy) { throw new NotImplementedException(); }
Expression MakeElementHandler([NotNull] Type elementType, [NotNull] Expression tagNameExpr, [NotNull] Expression tagValueExpr, NullPolicy elementPolicy, [NotNull] string nullElementMsg, [NotNull] Func <Expression, Expression> addTagExprFunc) { if (tagValueExpr.Type != elementType) { // In case value getter's return type is different from value return type (e.g. Array.GetValue(int)) tagValueExpr = Expression.Convert(tagValueExpr, elementType); } if (elementType.IsPrimitive || elementType.IsEnum) { //=== Serializing primitives and enums === // tag.Add( new NbtTag(kvp.Key, kvp.Value) ); return(addTagExprFunc(MakeNbtTagCtor(elementType, tagNameExpr, tagValueExpr))); } else if (SerializationUtil.IsDirectlyMappedType(elementType)) { //=== Serializing directly-mapped reference types (byte[], int[], string) === // declare a local var, which will hold the property's value ParameterExpression varElementValue = Expression.Parameter(elementType, "elementValue"); // Primary path, in case element value is not null: // iDictTag.Add(new NbtTag(kvp.Key, <getValueExpr>)); Expression addElementExpr = addTagExprFunc(MakeNbtTagCtor(elementType, tagNameExpr, tagValueExpr)); // Fallback path, in case element value is null and elementPolicy is InsertDefaults: // Add a default-value tag to the list: listTag.Add(new NbtTag(null, <default>)) Expression defaultValExpr = Expression.Constant(SerializationUtil.GetDefaultValue(elementType)); Expression defaultElementExpr = addTagExprFunc(MakeNbtTagCtor(elementType, tagNameExpr, defaultValExpr)); // generate the appropriate enclosing expressions, depending on NullPolicy return(NbtCompiler.MakeNullHandler(varElementValue, tagValueExpr, elementPolicy, addElementExpr, defaultElementExpr, nullElementMsg)); } else { //=== Serializing everything else === // Check if this is an IList-of-ILists Type iListImpl = SerializationUtil.GetGenericInterfaceImpl(elementType, typeof(IList <>)); Type iDictImpl = SerializationUtil.GetStringIDictionaryImpl(elementType); // check if this type can handle its own serialization if (typeof(INbtSerializable).IsAssignableFrom(elementType)) { // element is INbtSerializable MethodInfo serializeMethod = elementType.GetMethod("Serialize", new[] { typeof(string) }); Expression newTagExpr = Expression.Call(tagValueExpr, serializeMethod, tagNameExpr); return(addTagExprFunc(newTagExpr)); } else if (typeof(NbtTag).IsAssignableFrom(elementType)) { // element is NbtTag return(MakeNbtTagHandler( elementType, elementType, tagNameExpr, tagValueExpr, elementPolicy, nullElementMsg, expr => expr, addTagExprFunc)); } else if (typeof(NbtFile).IsAssignableFrom(elementType)) { // element is NbtFile return(MakeNbtTagHandler( typeof(NbtCompound), typeof(NbtFile), tagNameExpr, tagValueExpr, elementPolicy, nullElementMsg, expr => Expression.MakeMemberAccess(expr, NbtFileRootTagProperty), addTagExprFunc)); } else if (iListImpl != null) { // element is IList<?> Type subElementType = iListImpl.GetGenericArguments()[0]; return(MakeIListHandler(tagValueExpr, subElementType, tagNameExpr, elementPolicy, elementPolicy, nullElementMsg, nullElementMsg, addTagExprFunc)); } else if (iDictImpl != null) { // element is IDictionary<string,?> return(MakeStringIDictionaryHandler(tagNameExpr, tagValueExpr, iDictImpl, elementPolicy, elementPolicy, nullElementMsg, nullElementMsg, addTagExprFunc)); } else { // Get NbtSerialize<T> method for elementType Expression makeElementTagExpr = callResolver.MakeCall(elementType, tagNameExpr, tagValueExpr); // declare a local var, which will hold the element's value ParameterExpression varElementValue = Expression.Parameter(elementType, "elementValue"); // Primary path, adds the newly-made Compound tag to our list Expression addSerializedCompoundExpr = addTagExprFunc(makeElementTagExpr); // Fallback path, in case element's value is null and NullPolicy is InsertDefaults Expression addEmptyCompoundExpr = addTagExprFunc(Expression.New(NbtCompoundCtor, tagNameExpr)); // Generate the appropriate enclosing expressions, which choose path depending on NullPolicy return(NbtCompiler.MakeNullHandler(varElementValue, tagValueExpr, elementPolicy, addSerializedCompoundExpr, addEmptyCompoundExpr, nullElementMsg)); } } }
Expression MakeIListHandler([NotNull] Expression getIListExpr, [NotNull] Type elementType, [NotNull] Expression tagNameExpr, NullPolicy selfPolicy, NullPolicy elementPolicy, [NotNull] string selfNullMsg, [NotNull] string elementNullMsg, [NotNull] Func<Expression, Expression> processTagExpr) { Type listType = getIListExpr.Type; // Declare locals ParameterExpression varIList = Expression.Parameter(listType, "iList"); ParameterExpression varListTag = Expression.Parameter(typeof(NbtList), "listTag"); ParameterExpression varLength = Expression.Parameter(typeof(int), "length"); ParameterExpression varIndex = Expression.Parameter(typeof(int), "i"); // Find getters for this IList MethodInfo countGetterImpl, itemGetterImpl; if (listType.IsArray) { // Although Array claims to implement IList<>, there is no way to retrieve // the interface implementation: it's handled in an unusual way by the runtime. // So we have to resort to getting Length/GetValue instead of Count/Item countGetterImpl = listType.GetProperty("Length").GetGetMethod(); itemGetterImpl = listType.GetMethod("GetValue", new[] { typeof(int) }); } else { // For non-array IList<> types, grab this.Count getter (which maps to get_Count()) countGetterImpl = SerializationUtil.GetGenericInterfaceMethodImpl( listType, typeof(ICollection<>), "get_Count", new Type[0]); // ...and the getter for indexer this[int], which maps to get_Item(int) itemGetterImpl = SerializationUtil.GetGenericInterfaceMethodImpl( listType, typeof(IList<>), "get_Item", new[] { typeof(int) }); } // Create handler for a single element Expression getElementExpr = Expression.Call(varIList, itemGetterImpl, varIndex); Expression getCountExpr = Expression.Call(varIList, countGetterImpl); Expression handleOneElementExpr = MakeElementHandler( elementType, NbtCompiler.NullStringExpr, getElementExpr, elementPolicy, elementNullMsg, tag => Expression.Call(varListTag, NbtListAddMethod, tag)); // Arrange tag construction in a loop LabelTarget loopBreak = Expression.Label(typeof(void)); Expression mainLoop = // while (true) Expression.Loop( Expression.Block( // if (i >= length) break; Expression.IfThen( Expression.GreaterThanOrEqual(varIndex, varLength), Expression.Break(loopBreak)), // <process and add one element to the list> handleOneElementExpr, // ++i; Expression.PreIncrementAssign(varIndex)), loopBreak); // new NbtList(tagName, NbtTagType.*) Expression makeListTagExpr = Expression.New(NbtListCtor, tagNameExpr, Expression.Constant(GetNbtTagType(elementType))); // Fallback path, in case value our IList null and NullPolicy is InsertDefaults: // Add an empty list to root. Expression defaultValExpr = processTagExpr(makeListTagExpr); // Primary path, in case our IList is not null: // Package the list-building loop into a neat block, with locals Expression makeTagExpr = Expression.Block( new[] { varListTag, varIndex, varLength }, // NbtList listTag = new NbtList(tagName, NbtTagType.*); Expression.Assign(varListTag, makeListTagExpr), // int length = iList.Count; Expression.Assign(varLength, getCountExpr), // int i=0; Expression.Assign(varIndex, Expression.Constant(0)), // (fill the list tag) mainLoop, // rootTag.Add( listTag ); processTagExpr(varListTag)); // Generate the appropriate enclosing expressions, which choose path depending on NullPolicy return NbtCompiler.MakeNullHandler(varIList, getIListExpr, selfPolicy, makeTagExpr, defaultValExpr, selfNullMsg); }
Expression MakeElementHandler([NotNull] Type elementType, [NotNull] Expression tagNameExpr, [NotNull] Expression tagValueExpr, NullPolicy elementPolicy, [NotNull] string nullElementMsg, [NotNull] Func<Expression, Expression> addTagExprFunc) { if (tagValueExpr.Type != elementType) { tagValueExpr = Expression.Convert(tagValueExpr, elementType); } if (elementType.IsPrimitive || elementType.IsEnum) { //=== Serializing primitives and enums === // tag.Add( new NbtTag(kvp.Key, kvp.Value) ); return addTagExprFunc(MakeNbtTagCtor(elementType, tagNameExpr, tagValueExpr)); } else if (SerializationUtil.IsDirectlyMappedType(elementType)) { //=== Serializing directly-mapped reference types (byte[], int[], string) === // declare a local var, which will hold the property's value ParameterExpression varElementValue = Expression.Parameter(elementType, "elementValue"); // Primary path, in case element value is not null: // iDictTag.Add(new NbtTag(kvp.Key, <getValueExpr>)); Expression addElementExpr = addTagExprFunc(MakeNbtTagCtor(elementType, tagNameExpr, tagValueExpr)); // Fallback path, in case element value is null and elementPolicy is InsertDefaults: // Add a default-value tag to the list: listTag.Add(new NbtTag(null, <default>)) Expression defaultValExpr = Expression.Constant(SerializationUtil.GetDefaultValue(elementType)); Expression defaultElementExpr = addTagExprFunc(MakeNbtTagCtor(elementType, tagNameExpr, defaultValExpr)); // generate the appropriate enclosing expressions, depending on NullPolicy return NbtCompiler.MakeNullHandler(varElementValue, tagValueExpr, elementPolicy, addElementExpr, defaultElementExpr, nullElementMsg); } else { //=== Serializing everything else === // Check if this is an IList-of-ILists Type iListImpl = SerializationUtil.GetGenericInterfaceImpl(elementType, typeof(IList<>)); Type iDictImpl = SerializationUtil.GetStringIDictionaryImpl(elementType); // check if this type can handle its own serialization if (typeof(INbtSerializable).IsAssignableFrom(elementType)) { // element is INbtSerializable MethodInfo serializeMethod = elementType.GetMethod("Serialize", new[] { typeof(string) }); Expression newTagExpr = Expression.Call(tagValueExpr, serializeMethod, tagNameExpr); return addTagExprFunc(newTagExpr); } else if (typeof(NbtTag).IsAssignableFrom(elementType)) { // element is NbtTag return MakeNbtTagHandler( elementType, elementType, tagNameExpr, tagValueExpr, elementPolicy, nullElementMsg, expr => expr, addTagExprFunc); } else if (typeof(NbtFile).IsAssignableFrom(elementType)) { // element is NbtFile PropertyInfo rootTagProp = typeof(NbtFile).GetProperty("RootTag"); return MakeNbtTagHandler( typeof(NbtCompound), typeof(NbtFile), tagNameExpr, tagValueExpr, elementPolicy, nullElementMsg, expr => Expression.MakeMemberAccess(expr, rootTagProp), addTagExprFunc); } else if (iListImpl != null) { // element is IList<?> Type subElementType = iListImpl.GetGenericArguments()[0]; return MakeIListHandler(tagValueExpr, subElementType, tagNameExpr, elementPolicy, elementPolicy, nullElementMsg, nullElementMsg, addTagExprFunc); } else if (iDictImpl != null) { // element is IDictionary<string,?> return MakeStringIDictionaryHandler(tagNameExpr, tagValueExpr, iDictImpl, elementPolicy, elementPolicy, nullElementMsg, nullElementMsg, addTagExprFunc); } else { // Get NbtSerialize<T> method for elementType Expression makeElementTagExpr = callResolver.MakeCall(elementType, tagNameExpr, tagValueExpr); // declare a local var, which will hold the element's value ParameterExpression varElementValue = Expression.Parameter(elementType, "elementValue"); // Primary path, adds the newly-made Compound tag to our list Expression addSerializedCompoundExpr = addTagExprFunc(makeElementTagExpr); // Fallback path, in case element's value is null and NullPolicy is InsertDefaults Expression addEmptyCompoundExpr = addTagExprFunc(Expression.New(NbtCompoundCtor, tagNameExpr)); // Generate the appropriate enclosing expressions, which choose path depending on NullPolicy return NbtCompiler.MakeNullHandler(varElementValue, tagValueExpr, elementPolicy, addSerializedCompoundExpr, addEmptyCompoundExpr, nullElementMsg); } } }
public override Expression HandleStringIDictionary(string tagName, PropertyInfo property, Type iDictImpl, NullPolicy selfPolicy, NullPolicy elementPolicy) { Expression getIDictExpr = Expression.MakeMemberAccess(argValue, property); string nullElementMessage = MakeElementNullMessage(property); string nullMessage = MakePropertyNullMessage(property); return MakeStringIDictionaryHandler( Expression.Constant(tagName, typeof(string)), getIDictExpr, iDictImpl, selfPolicy, elementPolicy, nullMessage, nullElementMessage, expr => Expression.Call(varRootTag, NbtCompoundAddMethod, expr)); }
public override Expression HandleNbtTag(string tagName, PropertyInfo property, NullPolicy selfPolicy) { // Add tag directly to the list return MakeNbtTagPropertyHandler(property, tagName, property.PropertyType, selfPolicy, expr => expr); }
public override Expression HandleNbtFile(string tagName, PropertyInfo property, NullPolicy selfPolicy) { // Add NbtFile's root tag directly to the list PropertyInfo rootTagProp = typeof(NbtFile).GetProperty("RootTag"); return MakeNbtTagPropertyHandler(property, tagName, typeof(NbtCompound), selfPolicy, expr => Expression.MakeMemberAccess(expr, rootTagProp)); }
public override Expression HandleINbtSerializable(string tagName, PropertyInfo property, NullPolicy selfPolicy) { MethodInfo serializeMethod = property.PropertyType.GetMethod("Serialize", new[] { typeof(string) }); ParameterExpression varValue = Expression.Parameter(property.PropertyType, "value"); string nullMsg = MakePropertyNullMessage(property); // rootTag.Add( value.Serialize() ) Expression serializeExpr = Expression.Call( varRootTag, NbtCompoundAddMethod, Expression.Call(varValue, serializeMethod, Expression.Constant(tagName))); // Fallback path, in case value is null and NullPolicy is InsertDefaults Expression defaultExpr = Expression.New(NbtCompoundCtor, Expression.Constant(tagName)); // Getter for the property value Expression propValue = Expression.MakeMemberAccess(argValue, property); return NbtCompiler.MakeNullHandler(varValue, propValue, selfPolicy, serializeExpr, defaultExpr, nullMsg); }
public override Expression HandleIList(string tagName, PropertyInfo property, Type iListImpl, NullPolicy selfPolicy, NullPolicy elementPolicy) { // Getter for the property value Expression getPropertyExpr = Expression.MakeMemberAccess(argValue, property); Type elementType = iListImpl.GetGenericArguments()[0]; Expression tagNameExpr = Expression.Constant(tagName, typeof(string)); string selfNullMsg = MakePropertyNullMessage(property); string elementNullMsg = MakeElementNullMessage(property); return MakeIListHandler(getPropertyExpr, elementType, tagNameExpr, selfPolicy, elementPolicy, selfNullMsg, elementNullMsg, expr => Expression.Call(varRootTag, NbtCompoundAddMethod, expr)); }
public override Expression HandleINbtSerializable(string tagName, PropertyInfo property, NullPolicy selfPolicy) { MethodInfo serializeMethod = property.PropertyType.GetMethod("Serialize", new[] { typeof(string) }); ParameterExpression varValue = Expression.Parameter(property.PropertyType, "value"); string nullMsg = MakePropertyNullMessage(property); // rootTag.Add( value.Serialize() ) Expression serializeExpr = Expression.Call( varRootTag, NbtCompoundAddMethod, Expression.Call(varValue, serializeMethod, Expression.Constant(tagName))); // Fallback path, in case value is null and NullPolicy is InsertDefaults Expression defaultExpr = Expression.New(NbtCompoundCtor, Expression.Constant(tagName)); // Getter for the property value Expression propValue = Expression.MakeMemberAccess(argValue, property); return(NbtCompiler.MakeNullHandler(varValue, propValue, selfPolicy, serializeExpr, defaultExpr, nullMsg)); }
public override Expression HandleStringIDictionary(string tagName, PropertyInfo property, Type iDictImpl, NullPolicy selfPolicy, NullPolicy elementPolicy) { throw new NotImplementedException(); }
Expression MakeNbtTagHandler([NotNull] Type tagType, [NotNull] Type valueType, [NotNull] Expression tagNameExpr, [NotNull] Expression getPropertyExpr, NullPolicy selfPolicy, [NotNull] String nullMsg, [NotNull] Func<ParameterExpression, Expression> conversionFunc, [NotNull] Func<Expression, Expression> processTagExpr) { // declare a local var, which will hold the property's value ParameterExpression varValue = Expression.Parameter(valueType, "value"); // Primary path, adds the root tag of the NbtFile Expression makeTagExpr = processTagExpr(conversionFunc(varValue)); // Fallback path, in case value is null and NullPolicy is InsertDefaults ConstructorInfo tagCtor; if (tagType == typeof(NbtTag)) { tagCtor = NbtCompoundCtor; } else { tagCtor = tagType.GetConstructor(new[] { typeof(string) }); } Expression defaultVal = Expression.New(tagCtor, tagNameExpr); Expression defaultValExpr = processTagExpr(defaultVal); // Generate the appropriate enclosing expressions, which choose path depending on NullPolicy return NbtCompiler.MakeNullHandler(varValue, getPropertyExpr, selfPolicy, makeTagExpr, defaultValExpr, nullMsg); }
Expression MakeNbtTagPropertyHandler([NotNull] PropertyInfo property, [NotNull] string tagName, Type tagType, NullPolicy selfPolicy, [NotNull] Func<ParameterExpression, Expression> conversionFunc) { // Getter for the property value Expression getPropertyExpr = Expression.MakeMemberAccess(argValue, property); string nullMsg = MakePropertyNullMessage(property); Expression tagNameExpr = Expression.Constant(tagName, typeof(string)); // Generate the appropriate enclosing expressions, which choose path depending on NullPolicy return MakeNbtTagHandler(tagType, property.PropertyType, tagNameExpr, getPropertyExpr, selfPolicy, nullMsg, conversionFunc, tagExpr => Expression.Call(varRootTag, NbtCompoundAddMethod, tagExpr)); }
Expression MakeStringIDictionaryHandler([NotNull] Expression tagNameExpr, [NotNull] Expression getIDictExpr, [NotNull] Type iDictImpl, NullPolicy selfPolicy, NullPolicy elementPolicy, [NotNull] string selfNullMsg, [NotNull] string elementNullMsg, [NotNull] Func<Expression, Expression> processTagExpr) { Type elementType = iDictImpl.GetGenericArguments()[1]; // find type of KeyValuePair<string,?> that the enumerator will return Type kvpType = typeof(KeyValuePair<,>).MakeGenericType(iDictImpl.GetGenericArguments()); PropertyInfo keyProp = kvpType.GetProperty("Key"); PropertyInfo valueProp = kvpType.GetProperty("Value"); // locate IDictionary.GetEnumerator() Type enumerableType = typeof(IEnumerable<>).MakeGenericType(kvpType); Type enumeratorType = typeof(IEnumerator<>).MakeGenericType(kvpType); MethodInfo getEnumeratorImpl = SerializationUtil.GetGenericInterfaceMethodImpl( iDictImpl, enumerableType, "GetEnumerator", Type.EmptyTypes); // locate IEnumerator.MoveNext() MethodInfo moveNextMethod = typeof(IEnumerator).GetMethod("MoveNext"); MethodInfo disposeMethod = typeof(IDisposable).GetMethod("Dispose"); PropertyInfo currentProp = enumeratorType.GetProperty("Current"); ParameterExpression varIDict = Expression.Parameter(iDictImpl, "iDict"); ParameterExpression varCompTag = Expression.Parameter(typeof(NbtCompound), "compTag"); ParameterExpression varEnumerator = Expression.Parameter(enumeratorType, "enumerator"); ParameterExpression varKvp = Expression.Parameter(kvpType, "element"); // generate handlers for individual elements Expression getNameExpr = Expression.MakeMemberAccess(varKvp, keyProp); Expression getValueExpr = Expression.MakeMemberAccess(varKvp, valueProp); Expression handleOneElementExpr = MakeElementHandler( elementType, getNameExpr, getValueExpr, elementPolicy, elementNullMsg, tag => Expression.Call(varCompTag, NbtCompoundAddMethod, tag)); // Make glue code to hold everything together LabelTarget loopBreak = Expression.Label(typeof(void)); Expression loopBody = Expression.Block( new[] { varKvp }, Expression.Assign(varKvp, Expression.MakeMemberAccess(varEnumerator, currentProp)), handleOneElementExpr); Expression makeIDictTagExpr = Expression.Block( new[] { varCompTag, varEnumerator }, // varCompTag = new NbtCompound(tagName) Expression.Assign(varCompTag, Expression.New(NbtCompoundCtor, tagNameExpr)), // varEnumerator = iDict.GetEnumerator() Expression.Assign(varEnumerator, Expression.Call(varIDict, getEnumeratorImpl)), // try { Expression.MakeTry( typeof(void), // while (enumerator.MoveNext()) <loopBody>; Expression.Loop( Expression.IfThenElse(Expression.Call(varEnumerator, moveNextMethod), loopBody, Expression.Break(loopBreak)), loopBreak), // } finally { enumerator.Dispose(); } Expression.Call(varEnumerator, disposeMethod), null, null), processTagExpr(varCompTag)); // default value (in case selfPolicy is InsertDefault): new NbtCompound(tagName) Expression defaultValExpr = Expression.New(NbtCompoundCtor, tagNameExpr); return NbtCompiler.MakeNullHandler(varIDict, getIDictExpr, selfPolicy, makeIDictTagExpr, defaultValExpr, selfNullMsg); }
public abstract Expression HandleINbtSerializable([NotNull] string tagName, [NotNull] PropertyInfo property, NullPolicy selfPolicy);
NbtTag HandleElement(string tagName, object value, NullPolicy nullPolicy) { throw new NotImplementedException(); }
public abstract Expression HandleIList([NotNull] string tagName, [NotNull] PropertyInfo property, [NotNull] Type iListImpl, NullPolicy selfPolicy, NullPolicy elementPolicy);
NbtTag SerializeList(string tagName, IList valueAsArray, Type elementType, NullPolicy elementNullPolicy) { NbtTagType listType; if (elementType == typeof(byte) || elementType == typeof(sbyte) || elementType == typeof(bool)) { listType = NbtTagType.Byte; } else if (elementType == typeof(byte[])) { listType = NbtTagType.ByteArray; } else if (elementType == typeof(double)) { listType = NbtTagType.Double; } else if (elementType == typeof(float)) { listType = NbtTagType.Float; } else if (elementType == typeof(int) || elementType == typeof(uint)) { listType = NbtTagType.Int; } else if (elementType == typeof(int[])) { listType = NbtTagType.IntArray; } else if (elementType == typeof(long) || elementType == typeof(ulong)) { listType = NbtTagType.Long; } else if (elementType == typeof(short) || elementType == typeof(ushort)) { listType = NbtTagType.Short; } else if (elementType == typeof(string)) { listType = NbtTagType.String; } else { listType = NbtTagType.Compound; } var list = new NbtList(tagName, listType); if (elementType.IsPrimitive) { // speedy serialization for basic types for (int i = 0; i < valueAsArray.Count; i++) { list.Add(SerializePrimitiveType(null, valueAsArray[i])); } } else if (SerializationUtil.IsDirectlyMappedType(elementType)) { // speedy serialization for directly-mapped types for (int i = 0; i < valueAsArray.Count; i++) { var value = valueAsArray[i]; if (value == null) { switch (elementNullPolicy) { case NullPolicy.Error: throw new NullReferenceException("Null elements not allowed for tag " + tagName); case NullPolicy.InsertDefault: list.Add(Serialize(SerializationUtil.GetDefaultValue(elementType), true)); break; case NullPolicy.Ignore: continue; } } else { list.Add(Serialize(valueAsArray[i], true)); } } } else { // serialize complex types var innerSerializer = new NbtSerializer(elementType); for (int i = 0; i < valueAsArray.Count; i++) { var value = valueAsArray[i]; if (value == null) { switch (elementNullPolicy) { case NullPolicy.Error: throw new NullReferenceException("Null elements not allowed for tag " + tagName); case NullPolicy.Ignore: continue; case NullPolicy.InsertDefault: // TODO break; } } else { list.Add(innerSerializer.Serialize(valueAsArray[i], null)); } } } return list; }
public override Expression HandleINbtSerializable(string tagName, PropertyInfo property, NullPolicy selfPolicy) { throw new NotImplementedException(); }
public abstract Expression HandleDirectlyMappedType([NotNull] string tagName, [NotNull] PropertyInfo property, NullPolicy selfPolicy);
public override Expression HandleNbtTag(string tagName, PropertyInfo property, NullPolicy selfPolicy) { // Add tag directly to the list return(MakeNbtTagPropertyHandler(property, tagName, property.PropertyType, selfPolicy, expr => expr)); }
public NullPolicyAttribute(NullPolicy selfPolicy, NullPolicy elementPolicy) { SelfPolicy = selfPolicy; ElementPolicy = elementPolicy; }
public abstract Expression HandleCompoundObject([NotNull] string tagName, [NotNull] PropertyInfo property, NullPolicy selfPolicy);
Expression MakeIListHandler([NotNull] Expression getIListExpr, [NotNull] Type elementType, [NotNull] Expression tagNameExpr, NullPolicy selfPolicy, NullPolicy elementPolicy, [NotNull] string selfNullMsg, [NotNull] string elementNullMsg, [NotNull] Func <Expression, Expression> processTagExpr) { Type listType = getIListExpr.Type; // Declare locals ParameterExpression varIList = Expression.Parameter(listType, "iList"); ParameterExpression varListTag = Expression.Parameter(typeof(NbtList), "listTag"); ParameterExpression varLength = Expression.Parameter(typeof(int), "length"); ParameterExpression varIndex = Expression.Parameter(typeof(int), "i"); // Find getters for this IList MethodInfo countGetterImpl, itemGetterImpl; if (listType.IsArray) { // Although Array claims to implement IList<>, there is no way to retrieve // the interface implementation: it's handled in an unusual way by the runtime. // So we have to resort to getting Length/GetValue instead of Count/Item countGetterImpl = listType.GetProperty("Length").GetGetMethod(); itemGetterImpl = listType.GetMethod("GetValue", new[] { typeof(int) }); } else { // For non-array IList<> types, grab this.Count getter (which maps to get_Count()) countGetterImpl = SerializationUtil.GetGenericInterfaceMethodImpl( listType, typeof(ICollection <>), "get_Count", Type.EmptyTypes); // ...and the getter for indexer this[int], which maps to get_Item(int) itemGetterImpl = SerializationUtil.GetGenericInterfaceMethodImpl( listType, typeof(IList <>), "get_Item", new[] { typeof(int) }); } // Create handler for a single element Expression getElementExpr = Expression.Call(varIList, itemGetterImpl, varIndex); Expression getCountExpr = Expression.Call(varIList, countGetterImpl); Expression handleOneElementExpr = MakeElementHandler( elementType, NbtCompiler.NullStringExpr, getElementExpr, elementPolicy, elementNullMsg, tag => Expression.Call(varListTag, NbtListAddMethod, tag)); // Arrange tag construction in a loop LabelTarget loopBreak = Expression.Label(typeof(void)); Expression mainLoop = // while (true) Expression.Loop( Expression.Block( // if (i >= length) break; Expression.IfThen( Expression.GreaterThanOrEqual(varIndex, varLength), Expression.Break(loopBreak)), // <process and add one element to the list> handleOneElementExpr, // ++i; Expression.PreIncrementAssign(varIndex)), loopBreak); // new NbtList(tagName, NbtTagType.*) ConstructorInfo listTagCtor = typeof(NbtList).GetConstructor(new[] { typeof(string), typeof(NbtTagType) }); Expression makeListTagExpr = Expression.New(listTagCtor, tagNameExpr, Expression.Constant(GetNbtTagType(elementType))); // Fallback path, in case value our IList null and NullPolicy is InsertDefaults: // Add an empty list to root. Expression defaultValExpr = processTagExpr(makeListTagExpr); // Primary path, in case our IList is not null: // Package the list-building loop into a neat block, with locals Expression makeTagExpr = Expression.Block( new[] { varListTag, varIndex, varLength }, // NbtList listTag = new NbtList(tagName, NbtTagType.*); Expression.Assign(varListTag, makeListTagExpr), // int length = iList.Count; Expression.Assign(varLength, getCountExpr), // int i=0; Expression.Assign(varIndex, Expression.Constant(0)), // (fill the list tag) mainLoop, // rootTag.Add( listTag ); processTagExpr(varListTag)); // Generate the appropriate enclosing expressions, which choose path depending on NullPolicy return(NbtCompiler.MakeNullHandler(varIList, getIListExpr, selfPolicy, makeTagExpr, defaultValExpr, selfNullMsg)); }
public override Expression HandleNbtTag(string tagName, PropertyInfo property, NullPolicy selfPolicy) { throw new NotImplementedException(); }
public override Expression HandleNbtFile(string tagName, PropertyInfo property, NullPolicy selfPolicy) { // Add NbtFile's root tag directly to the list return(MakeNbtTagPropertyHandler( property, tagName, typeof(NbtCompound), selfPolicy, expr => Expression.MakeMemberAccess(expr, NbtFileRootTagProperty))); }
public NullPolicyAttribute(NullPolicy selfPolicy) { SelfPolicy = selfPolicy; ElementPolicy = NullPolicy.Default; }
public override Expression HandleCompoundObject(string tagName, PropertyInfo property, NullPolicy selfPolicy) { return(MakeNbtTagPropertyHandler( property, tagName, typeof(NbtCompound), selfPolicy, expr => callResolver.MakeCall(property.PropertyType, Expression.Constant(tagName, typeof(string)), expr))); }
Expression MakeStringIDictionaryHandler([NotNull] Expression tagNameExpr, [NotNull] Expression getIDictExpr, [NotNull] Type iDictImpl, NullPolicy selfPolicy, NullPolicy elementPolicy, [NotNull] string selfNullMsg, [NotNull] string elementNullMsg, [NotNull] Func <Expression, Expression> processTagExpr) { Type elementType = iDictImpl.GetGenericArguments()[1]; // find type of KeyValuePair<string,?> that the enumerator will return Type kvpType = typeof(KeyValuePair <,>).MakeGenericType(iDictImpl.GetGenericArguments()); PropertyInfo keyProp = kvpType.GetProperty("Key"); PropertyInfo valueProp = kvpType.GetProperty("Value"); // locate IDictionary.GetEnumerator() Type enumerableType = typeof(IEnumerable <>).MakeGenericType(kvpType); Type enumeratorType = typeof(IEnumerator <>).MakeGenericType(kvpType); MethodInfo getEnumeratorImpl = SerializationUtil.GetGenericInterfaceMethodImpl( iDictImpl, enumerableType, "GetEnumerator", Type.EmptyTypes); // locate IEnumerator.MoveNext() MethodInfo moveNextMethod = typeof(IEnumerator).GetMethod("MoveNext"); MethodInfo disposeMethod = typeof(IDisposable).GetMethod("Dispose"); PropertyInfo currentProp = enumeratorType.GetProperty("Current"); ParameterExpression varIDict = Expression.Parameter(iDictImpl, "iDict"); ParameterExpression varCompTag = Expression.Parameter(typeof(NbtCompound), "compTag"); ParameterExpression varEnumerator = Expression.Parameter(enumeratorType, "enumerator"); ParameterExpression varKvp = Expression.Parameter(kvpType, "element"); // generate handlers for individual elements Expression getNameExpr = Expression.MakeMemberAccess(varKvp, keyProp); Expression getValueExpr = Expression.MakeMemberAccess(varKvp, valueProp); Expression handleOneElementExpr = MakeElementHandler( elementType, getNameExpr, getValueExpr, elementPolicy, elementNullMsg, tag => Expression.Call(varCompTag, NbtCompoundAddMethod, tag)); // Make glue code to hold everything together LabelTarget loopBreak = Expression.Label(typeof(void)); Expression loopBody = Expression.Block( new[] { varKvp }, Expression.Assign(varKvp, Expression.MakeMemberAccess(varEnumerator, currentProp)), handleOneElementExpr); Expression makeIDictTagExpr = Expression.Block( new[] { varCompTag, varEnumerator }, // varCompTag = new NbtCompound(tagName) Expression.Assign(varCompTag, Expression.New(NbtCompoundCtor, tagNameExpr)), // varEnumerator = iDict.GetEnumerator() Expression.Assign(varEnumerator, Expression.Call(varIDict, getEnumeratorImpl)), // try { Expression.MakeTry( typeof(void), // while (enumerator.MoveNext()) <loopBody>; Expression.Loop( Expression.IfThenElse(Expression.Call(varEnumerator, moveNextMethod), loopBody, Expression.Break(loopBreak)), loopBreak), // } finally { enumerator.Dispose(); } Expression.Call(varEnumerator, disposeMethod), null, null), processTagExpr(varCompTag)); // default value (in case selfPolicy is InsertDefault): new NbtCompound(tagName) Expression defaultValExpr = Expression.New(NbtCompoundCtor, tagNameExpr); return(NbtCompiler.MakeNullHandler(varIDict, getIDictExpr, selfPolicy, makeIDictTagExpr, defaultValExpr, selfNullMsg)); }
internal static Expression MakeNullHandler([NotNull] ParameterExpression varValue, [NotNull] Expression getPropertyExpr, NullPolicy policy, [NotNull] Expression nonNullExpr, [NotNull] Expression defaultValExpr, [NotNull] string exceptionMessage) { // locate the getter for this property Expression ifExpr; switch (policy) { case NullPolicy.Error: ifExpr = Expression.IfThenElse( // if (value==null) throw new NullReferenceException(exceptionMessage) Expression.ReferenceEqual(varValue, Expression.Constant(null)), Expression.Throw( Expression.New(NullReferenceExceptionCtor, Expression.Constant(exceptionMessage))), // else <nonNullExpr> nonNullExpr); break; case NullPolicy.Ignore: ifExpr = Expression.IfThen( // if (value!=null) <nonNullExpr> Expression.Not(Expression.ReferenceEqual(varValue, Expression.Constant(null))), nonNullExpr); break; case NullPolicy.InsertDefault: ifExpr = Expression.IfThenElse( // if (value==null) <defaultValExpr> Expression.ReferenceEqual(varValue, Expression.Constant(null)), defaultValExpr, // else <nonNullExpr> nonNullExpr); break; default: throw new ArgumentOutOfRangeException("Unrecognized value for NullPolicy: " + policy); } return Expression.Block( // var varValue = value.ThisProperty; new[] { varValue }, Expression.Assign(varValue, getPropertyExpr), // (check if value is null, and do something) ifExpr); }
public override Expression HandleCompoundObject(string tagName, PropertyInfo property, NullPolicy selfPolicy) { throw new NotImplementedException(); }
public abstract Expression HandleNbtTag([NotNull] string tagName, [NotNull] PropertyInfo property, NullPolicy selfPolicy);
// Generates an expression that creates an NbtTag for given property of a directly-mappable types. // Directly-mappable types are: primitives, enums, byte[], int[], and string. // HandlePrimitiveOrEnum is actually more efficient (and preferred by NbtCompiler) for primitives and enums, // because it skips boxing and NullPolicy checks. This one is pretty much only used for byte[]/int[]/string. public override Expression HandleDirectlyMappedType(string tagName, PropertyInfo property, NullPolicy selfPolicy) { // declare a local var, which will hold the property's value ParameterExpression varValue = Expression.Parameter(property.PropertyType); // Fallback path, in case value is null and NullPolicy is InsertDefaults Expression defaultVal = Expression.Constant(SerializationUtil.GetDefaultValue(property.PropertyType)); // varRootTag.Add( new NbtTag(tagName, <defaultVal>) ); Expression defaultValExpr = Expression.Call(varRootTag, NbtCompoundAddMethod, MakeNbtTagCtor(property.PropertyType, Expression.Constant(tagName, typeof(string)), defaultVal)); // varRootTag.Add( new NbtTag(tagName, <varValue>) ); Expression makeTagExpr = Expression.Call(varRootTag, NbtCompoundAddMethod, MakeNbtTagCtor(property.PropertyType, Expression.Constant(tagName, typeof(string)), varValue)); // Getter for the property value Expression getPropertyExpr = Expression.MakeMemberAccess(argValue, property); // generate the appropriate enclosing expressions, depending on NullPolicy return(NbtCompiler.MakeNullHandler(varValue, getPropertyExpr, selfPolicy, makeTagExpr, defaultValExpr, MakePropertyNullMessage(property))); }