Exemplo n.º 1
0
 internal NbtConverter([NotNull] Type contractType)
 {
     if (contractType == null) throw new ArgumentNullException("contractType");
     this.contractType = contractType;
     compiledSerializeDelegate = NbtCompiler.GetSerializer(contractType);
     compiledDeserializeDelegate = NbtCompiler.GetDeserializer(contractType);
 }
Exemplo n.º 2
0
 internal NbtConverter([NotNull] Type contractType)
 {
     if (contractType == null)
     {
         throw new ArgumentNullException("contractType");
     }
     this.contractType           = contractType;
     compiledSerializeDelegate   = NbtCompiler.GetSerializer(contractType);
     compiledDeserializeDelegate = NbtCompiler.GetDeserializer(contractType);
 }
Exemplo n.º 3
0
        static NbtSerialize CreateSerializer(Type type) {
            // This allows our function to call itself, while it is still being built up.
            NbtSerialize placeholderDelegate = null;
            // A closure is modified intentionally, at the end of this method:
            // placeholderDelegate will be replaced with reference to the compiled function.
            // ReSharper disable once AccessToModifiedClosure
            Expression<Func<NbtSerialize>> placeholderExpr = () => placeholderDelegate;
            ParentSerializers.Add(type, placeholderExpr);
            try {
                // Define function arguments
                ParameterExpression argTagName = Expression.Parameter(typeof(string), "tagName");
                ParameterExpression argValue = Expression.Parameter(type, "value");

                // Create our resolver and emitter
                var callResolver = new CallResolver();
                CodeEmitter codeEmitter = new SerializeCodeEmitter(argTagName, argValue, callResolver);

                // Define return label
                LabelTarget returnTarget = Expression.Label(codeEmitter.ReturnValue.Type);

                // Build up the type-specific list of expressions that perform serialization
                List<Expression> propSerializersList =
                    MakePropertySerializers(codeEmitter, type);

                if (callResolver.HasParameters) {
                    propSerializersList.InsertRange(0, callResolver.GetParameterAssignmentList());
                }

                Expression serializersExpr;
                if (propSerializersList.Count == 0) {
                    serializersExpr = Expression.Empty();
                } else if (propSerializersList.Count == 1) {
                    serializersExpr = propSerializersList[0];
                } else {
                    serializersExpr = Expression.Block(propSerializersList);
                }

                // Create function-wide variables -- includes root tag and serializer delegates
                var vars = new List<ParameterExpression> {
                    codeEmitter.ReturnValue
                };
                if (callResolver.HasParameters) {
                    vars.AddRange(callResolver.GetParameterList());
                }

                // Construct the method body
                BlockExpression method = Expression.Block(
                    vars,

                    // if( argValue == null )
                    Expression.IfThen(
                        Expression.ReferenceEqual(argValue, Expression.Constant(null)),
                        //  throw new ArgumentNullException("value");
                        Expression.Throw(Expression.New(ArgumentNullExceptionCtor, Expression.Constant("value")))),
                    codeEmitter.GetPreamble(),

                    // (run the generated serializing code)
                    serializersExpr,

                    // return varRootTag;
                    Expression.Return(returnTarget, codeEmitter.ReturnValue, codeEmitter.ReturnValue.Type),
                    Expression.Label(returnTarget, Expression.Constant(null, typeof(NbtCompound))));

                // compile
                Expression<NbtSerialize> methodLambda =
                    Expression.Lambda<NbtSerialize>(method, argTagName, argValue);

#if DEBUG_NBTSERIALIZE_COMPILER
                // When in debug mode, print the expression tree to stdout.
                PropertyInfo propInfo =
                    typeof(Expression)
                        .GetProperty("DebugView",
                                     BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance);

                var debugView = (string)propInfo.GetValue(methodLambda, null);
                Debug.WriteLine(debugView);
#endif

                NbtSerialize compiledMethod = methodLambda.Compile();

                // modify the closure created earlier, to allow recursive calls
                placeholderDelegate = compiledMethod;

                SerializerCache.Add(type, compiledMethod);
                return compiledMethod;
            } finally {
                ParentSerializers.Remove(type);
            }
        }