protected override ExpressionConstruct EmitMethodOfExpression(ExpressionTreeContext context, MethodBase method) { if (SerializerDebugging.DumpEnabled) { // LambdaExpression.CompileToMethod cannot handle RuntimeTypeHandle, but can handle Type constants. return(Expression.Constant(method)); } else { #if !NETFX_CORE // WinRT expression tree cannot handle Type constants, but handle RuntimeTypeHandle. #if DEBUG Contract.Assert(method.DeclaringType != null, "method.DeclaringType != null"); #endif // DEBUG return(Expression.Call(Metadata._MethodBase.GetMethodFromHandle, Expression.Constant(method.MethodHandle), Expression.Constant(method.DeclaringType.TypeHandle))); #else // WinRT expression tree cannot handle Type constants, and MethodHandle property is not exposed. // typeof( T ).GetRuntimeMethod( method.Name, ...{types}... ); return (Expression.Call( ReflectionHelpers.GetRuntimeMethodMethod, this.EmitTypeOfExpression(context, method.DeclaringType).Expression, Expression.Constant(method.Name), Expression.NewArrayInit( typeof(Type), method.GetParameters().Select(p => this.EmitTypeOfExpression(context, p.ParameterType).Expression) ) )); #endif } }
protected override ExpressionConstruct EmitForEachLoop( ExpressionTreeContext context, CollectionTraits collectionTraits, ExpressionConstruct collection, Func <ExpressionConstruct, ExpressionConstruct> loopBodyEmitter ) { var enumerator = Expression.Variable(collectionTraits.GetEnumeratorMethod.ReturnType, "enumerator"); var current = Expression.Variable(collectionTraits.ElementType, "current"); var moveNextMethod = Metadata._IEnumerator.FindEnumeratorMoveNextMethod(enumerator.Type); var currentProperty = Metadata._IEnumerator.FindEnumeratorCurrentProperty(enumerator.Type, collectionTraits); var endForEach = Expression.Label("END_FOREACH"); return (Expression.Block( new[] { enumerator, current }, Expression.Assign(enumerator, Expression.Call(collection, collectionTraits.GetEnumeratorMethod)), Expression.Loop( Expression.IfThenElse( Expression.Call(enumerator, moveNextMethod), Expression.Block( Expression.Assign(current, Expression.Property(enumerator, currentProperty)), loopBodyEmitter(current) ), Expression.Break(endForEach) ), endForEach ) )); }
protected override ExpressionConstruct EmitGetSerializerExpression(ExpressionTreeContext context, Type targetType, SerializingMember?memberInfo) { return (memberInfo == null || !targetType.GetIsEnum() ? Expression.Call( context.Context, Metadata._SerializationContext.GetSerializer1_Method.MakeGenericMethod(targetType) ) : this.EmitInvokeMethodExpression( context, context.Context, Metadata._SerializationContext.GetSerializer1_Parameter_Method.MakeGenericMethod(targetType), this.EmitBoxExpression( context, typeof(EnumSerializationMethod), this.EmitInvokeMethodExpression( context, null, Metadata._EnumMessagePackSerializerHelpers.DetermineEnumSerializationMethodMethod, context.Context, this.EmitTypeOfExpression(context, targetType), this.MakeEnumLiteral( context, typeof(EnumMemberSerializationMethod), memberInfo.Value.GetEnumMemberSerializationMethod() ) ) ) )); }
protected override ExpressionConstruct EmitEnumFromUnderlyingCastExpression( ExpressionTreeContext context, Type enumType, ExpressionConstruct underlyingValue) { return(Expression.Convert(underlyingValue, enumType)); }
protected override ExpressionConstruct EmitFieldOfExpression(ExpressionTreeContext context, FieldInfo field) { if (SerializerDebugging.DumpEnabled) { // LambdaExpression.CompileToMethod cannot handle RuntimeTypeHandle, but can handle Type constants. return(Expression.Constant(field)); } else { #if !NETFX_CORE #if DEBUG Contract.Assert(field.DeclaringType != null, "field.DeclaringType != null"); #endif // DEBUG return(Expression.Call(Metadata._FieldInfo.GetFieldFromHandle, Expression.Constant(field.FieldHandle), Expression.Constant(field.DeclaringType.TypeHandle))); #else // WinRT expression tree cannot handle Type constants, and MethodHandle property is not exposed. // typeof( T ).GetRuntimeField( field.Name ); return (Expression.Call( ReflectionHelpers.GetRuntimeFieldMethod, this.EmitTypeOfExpression(context, field.DeclaringType).Expression, Expression.Constant(field.Name) )); #endif } }
protected override ExpressionConstruct EmitMethodOfExpression(ExpressionTreeContext context, MethodBase method) { if (SerializerDebugging.DumpEnabled) { // LambdaExpression.CompileToMethod cannot handle RuntimeTypeHandle, but can handle Type constants. return(Expression.Constant(method)); } else { #if !NETFX_CORE // WinRT expression tree cannot handle Type constants, but handle RuntimeTypeHandle. return(Expression.Call(Metadata._MethodBase.GetMethodFromHandle, Expression.Constant(method.MethodHandle))); #else // WinRT expression tree cannot handle Type constants, and MethodHandle property is not exposed. // Overloading is not supported. // typeof( T ).GetRuntimeMethod( method.Name, null ); return (Expression.Call( typeof(RuntimeReflectionExtensions).GetRuntimeMethod("GetRuntimeMethod", new [] { typeof(Type), typeof(string), typeof(Type[]) }), this.EmitTypeOfExpression(context, method.DeclaringType).Expression, Expression.Constant(method.Name), Expression.NewArrayInit( typeof(Type), method.GetParameters().Select(p => this.EmitTypeOfExpression(context, p.ParameterType).Expression) ) )); #endif } }
private Delegate EmitMethodEpilogue <T>(ExpressionTreeContext context, Type delegateType, T method, ExpressionConstruct construct) { if (SerializerDebugging.TraceEnabled) { SerializerDebugging.TraceEvent("----{0}----", method); construct.ToString(SerializerDebugging.ILTraceWriter); SerializerDebugging.FlushTraceData(); } var lambda = Expression.Lambda( delegateType, construct.Expression, method.ToString(), false, context.GetCurrentParameters() ); #if !NETFX_CORE && !SILVERLIGHT if (SerializerDebugging.DumpEnabled) { var mb = this._typeBuilder.DefineMethod( method.ToString(), MethodAttributes.Public | MethodAttributes.Static, lambda.Type, lambda.Parameters.Select(e => e.Type).ToArray() ); lambda.CompileToMethod(mb); } #endif return(lambda.Compile()); }
protected override ExpressionConstruct EmitFieldOfExpression(ExpressionTreeContext context, FieldInfo field) { // ReSharper disable RedundantIfElseBlock if (SerializerDebugging.DumpEnabled) { // LambdaExpression.CompileToMethod cannot handle RuntimeTypeHandle, but can handle Type constants. return(Expression.Constant(field)); } else { #if !NETFX_CORE return(Expression.Call(Metadata._FieldInfo.GetFieldFromHandle, Expression.Constant(field.FieldHandle))); #else // WinRT expression tree cannot handle Type constants, and MethodHandle property is not exposed. // Overloading is not supported. // typeof( T ).GetRuntimeField( field.Name, null ); return (Expression.Call( typeof(RuntimeReflectionExtensions).GetRuntimeMethod("GetRuntimeField", new[] { typeof(Type), typeof(string), typeof(Type[]) }), this.EmitTypeOfExpression(context, field.DeclaringType).Expression, Expression.Constant(field.Name) )); #endif } // ReSharper restore RedundantIfElseBlock }
protected override ExpressionConstruct EmitEnumToUnderlyingCastExpression( ExpressionTreeContext context, Type underlyingType, ExpressionConstruct enumValue) { // ExpressionTree cannot handle enum to underlying type conversion... return(Expression.Convert(enumValue, underlyingType)); }
protected override ExpressionConstruct EmitSetArrayElementStatement(ExpressionTreeContext context, ExpressionConstruct array, ExpressionConstruct index, ExpressionConstruct value) { return (Expression.Assign( Expression.ArrayAccess(array, index), value )); }
protected override ExpressionConstruct EmitInvokeMethodExpression( ExpressionTreeContext context, ExpressionConstruct instance, MethodInfo method, IEnumerable <ExpressionConstruct> arguments ) { return (instance == null ? Expression.Call(method, arguments.Select(c => c.Expression)) : Expression.Call(instance, method, arguments.Select(c => c.Expression))); }
protected override void EmitMethodEpilogue(ExpressionTreeContext context, CollectionSerializerMethod method, ExpressionConstruct construct) { if (construct == null) { return; } context.SetDelegate(method, this.EmitMethodEpilogue(context, ExpressionTreeContext.CreateDelegateType <TObject>(method, SerializerClass, CollectionTraitsOfThis), method, construct)); }
protected override void EmitMethodEpilogue(ExpressionTreeContext context, EnumSerializerMethod method, ExpressionConstruct construct) { if (construct == null) { return; } context.SetDelegate(method, EmitMethodEpilogue(context, ExpressionTreeContext.CreateDelegateType <TObject>(method), method, construct)); }
protected override ExpressionConstruct EmitSequentialStatements(ExpressionTreeContext context, Type contextType, IEnumerable <ExpressionConstruct> statements) { var sts = statements.Where(s => s != null).ToArray(); return (Expression.Block( contextType, sts.Select(c => c.Expression).OfType <ParameterExpression>().Distinct(), // For declare and re-refer pattern sts.Where(c => c.IsSignificantReference || !(c.Expression is ParameterExpression)).Select(c => c.Expression) )); }
protected override ExpressionConstruct EmitLoadVariableExpression(ExpressionTreeContext context, ExpressionConstruct variable) { // Just use ParameterExpression. #if DEBUG Contract.Assert( (variable.Expression is ParameterExpression) && variable.ContextType != typeof(void), variable.Expression.ToString() ); #endif return(new ExpressionConstruct(variable, true)); }
protected override ExpressionConstruct EmitStringSwitchStatement(ExpressionTreeContext context, ExpressionConstruct target, IDictionary <string, ExpressionConstruct> cases, ExpressionConstruct defaultCase) { return (Expression.Switch( typeof(void), target, defaultCase, Metadata._String.op_Equality, cases.Select(kv => Expression.SwitchCase(kv.Value, Expression.Constant(kv.Key))).ToArray() )); }
protected override ExpressionConstruct EmitTypeOfExpression(ExpressionTreeContext context, Type type) { if (SerializerDebugging.DumpEnabled) { // LambdaExpression.CompileToMethod cannot handle RuntimeTypeHandle, but can handle Type constants. return(Expression.Constant(type)); } else { // WinRT expression tree cannot handle Type constants, but handle RuntimeTypeHandle. return(Expression.Call(Metadata._Type.GetTypeFromHandle, Expression.Constant(type.TypeHandle))); } }
protected override ExpressionConstruct EmitAndConditionalExpression( ExpressionTreeContext context, IList <ExpressionConstruct> conditionExpressions, ExpressionConstruct thenExpression, ExpressionConstruct elseExpression ) { return (Expression.IfThenElse( conditionExpressions.Aggregate((l, r) => Expression.AndAlso(l, r)), thenExpression, elseExpression )); }
protected override ExpressionConstruct EmitConditionalExpression( ExpressionTreeContext context, ExpressionConstruct conditionExpression, ExpressionConstruct thenExpression, ExpressionConstruct elseExpression ) { #if DEBUG Contract.Assert( elseExpression == null || (thenExpression.ContextType == elseExpression.ContextType), thenExpression.ContextType + " != " + (elseExpression == null ? "(null)" : elseExpression.ContextType.FullName) ); #endif return (elseExpression == null ? Expression.IfThen(conditionExpression, thenExpression) : thenExpression.ContextType == typeof(void) ? Expression.IfThenElse(conditionExpression, thenExpression, elseExpression) : Expression.Condition(conditionExpression, thenExpression, elseExpression)); }
protected override ExpressionConstruct EmitForLoop(ExpressionTreeContext context, ExpressionConstruct count, Func <ForLoopContext, ExpressionConstruct> loopBodyEmitter) { var counter = Expression.Variable(typeof(int), "i"); var loopContext = new ForLoopContext(counter); var endFor = Expression.Label("END_FOR"); return (Expression.Block( new[] { counter }, Expression.Loop( Expression.IfThenElse( Expression.LessThan(counter, count), Expression.Block( loopBodyEmitter(loopContext), Expression.Assign(counter, Expression.Increment(counter)) ), Expression.Break(endFor) ), endFor ) )); }
protected override ExpressionConstruct EmitTryFinally( ExpressionTreeContext context, ExpressionConstruct tryStatement, ExpressionConstruct finallyStatement ) { return(Expression.TryFinally(tryStatement, finallyStatement)); }
protected override void EmitMethodPrologue(ExpressionTreeContext context, EnumSerializerMethod method) { context.Reset(typeof(TObject)); context.SetCurrentMethod(typeof(TObject), method); }
protected override Func <SerializationContext, MessagePackSerializer <TObject> > CreateEnumSerializerConstructor(ExpressionTreeContext codeGenerationContext) { #if !NETFX_CORE && !SILVERLIGHT if (SerializerDebugging.DumpEnabled) { this._typeBuilder.CreateType(); } #endif // Get at this point to prevent unexpected context change. var packUnderyingValueTo = codeGenerationContext.GetPackUnderyingValueTo <TObject>(); var unpackFromUnderlyingValue = codeGenerationContext.GetUnpackFromUnderlyingValue <TObject>(); var targetType = typeof(ExpressionCallbackEnumMessagePackSerializer <>).MakeGenericType(typeof(TObject)); return (context => Activator.CreateInstance( targetType, context, EnumMessagePackSerializerHelpers.DetermineEnumSerializationMethod( context, typeof(TObject), EnumMemberSerializationMethod.Default ), packUnderyingValueTo, unpackFromUnderlyingValue ) as MessagePackSerializer <TObject>); }
protected override Func <SerializationContext, MessagePackSerializer <TObject> > CreateSerializerConstructor(ExpressionTreeContext codeGenerationContext) { #if !NETFX_CORE && !SILVERLIGHT if (SerializerDebugging.DumpEnabled) { this._typeBuilder.CreateType(); } #endif // Get at this point to prevent unexpected context change. var packToCore = codeGenerationContext.GetPackToCore <TObject>(); var unpackFromCore = codeGenerationContext.GetUnpackFromCore <TObject>(); var unpackToCore = codeGenerationContext.GetUnpackToCore <TObject>(); return (context => new ExpressionCallbackMessagePackSerializer <TObject>( context, packToCore, unpackFromCore, unpackToCore )); }
protected override ExpressionConstruct EmitSetField( ExpressionTreeContext context, ExpressionConstruct instance, FieldInfo field, ExpressionConstruct value ) { return(Expression.Assign(Expression.Field(instance, field), value)); }
protected override ExpressionConstruct EmitStoreVariableStatement( ExpressionTreeContext context, ExpressionConstruct variable, ExpressionConstruct value ) { return(Expression.Assign(variable, value)); }
protected override ExpressionConstruct EmitStoreVariableStatement(ExpressionTreeContext context, ExpressionConstruct variable) { // nop return(null); }
protected override ExpressionConstruct EmitThrowExpression( ExpressionTreeContext context, Type expressionType, ExpressionConstruct exceptionExpression ) { return(Expression.Throw(exceptionExpression, expressionType)); }
public static Func <SerializationContext, MessagePackSerializer <TObject> > CreateFactory <TObject>(ExpressionTreeContext codeGenerationContext, CollectionTraits traits, PolymorphismSchema schema) { // Get at this point to prevent unexpected context change. var packToCore = codeGenerationContext.GetPackToCore(); var unpackFromCore = codeGenerationContext.GetUnpackFromCore(); var unpackToCore = codeGenerationContext.GetUnpackToCore(); var createInstance = codeGenerationContext.GetCreateInstance(); var addItem = codeGenerationContext.GetAddItem(); switch (traits.DetailedCollectionType) { case CollectionDetailedKind.NonGenericEnumerable: { var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <IEnumerableCallbackSerializerFactory>( typeof(NonGenericEnumerableCallbackSerializerFactory <>).MakeGenericType(typeof(TObject)) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, unpackFromCore, addItem) as MessagePackSerializer <TObject>); } case CollectionDetailedKind.NonGenericCollection: { var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <IEnumerableCallbackSerializerFactory>( typeof(NonGenericCollectionCallbackSerializerFactory <>).MakeGenericType(typeof(TObject)) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, unpackFromCore, addItem) as MessagePackSerializer <TObject>); } case CollectionDetailedKind.NonGenericList: { var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <ICollectionCallbackSerializerFactory>( typeof(NonGenericListCallbackSerializerFactory <>).MakeGenericType(typeof(TObject)) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, addItem) as MessagePackSerializer <TObject>); } case CollectionDetailedKind.NonGenericDictionary: { var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <ICollectionCallbackSerializerFactory>( typeof(NonGenericDictionaryCallbackSerializerFactory <>).MakeGenericType(typeof(TObject)) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, addItem) as MessagePackSerializer <TObject>); } case CollectionDetailedKind.GenericEnumerable: { var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <IEnumerableCallbackSerializerFactory>( typeof(EnumerableCallbackSerializerFactory <,>).MakeGenericType(typeof(TObject), traits.ElementType) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, unpackFromCore, addItem) as MessagePackSerializer <TObject>); } case CollectionDetailedKind.GenericCollection: case CollectionDetailedKind.GenericSet: case CollectionDetailedKind.GenericList: { var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <ICollectionCallbackSerializerFactory>( typeof(CollectionCallbackSerializerFactory <,>).MakeGenericType(typeof(TObject), traits.ElementType) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, addItem) as MessagePackSerializer <TObject>); } #if !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) case CollectionDetailedKind.GenericReadOnlyCollection: case CollectionDetailedKind.GenericReadOnlyList: { var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <ICollectionCallbackSerializerFactory>( typeof(ReadOnlyCollectionCallbackSerializerFactory <,>).MakeGenericType(typeof(TObject), traits.ElementType) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, addItem) as MessagePackSerializer <TObject>); } #endif // !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) case CollectionDetailedKind.GenericDictionary: { var keyValuePairGenericArguments = traits.ElementType.GetGenericArguments(); var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <ICollectionCallbackSerializerFactory>( typeof(DictionaryCallbackSerializerFactory <, ,>).MakeGenericType( typeof(TObject), keyValuePairGenericArguments[0], keyValuePairGenericArguments[1] ) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, addItem) as MessagePackSerializer <TObject>); } #if !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) case CollectionDetailedKind.GenericReadOnlyDictionary: { var keyValuePairGenericArguments = traits.ElementType.GetGenericArguments(); var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <ICollectionCallbackSerializerFactory>( typeof(ReadOnlyDictionaryCallbackSerializerFactory <, ,>).MakeGenericType( typeof(TObject), keyValuePairGenericArguments[0], keyValuePairGenericArguments[1] ) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, schema, createInstance, addItem) as MessagePackSerializer <TObject>); } #endif // !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) default: { var factory = ReflectionExtensions.CreateInstancePreservingExceptionType <ICallbackSerializerFactory>( typeof(CallbackSerializerFactory <>).MakeGenericType( typeof(TObject) ) ); #if DEBUG Contract.Assert(factory != null); #endif // DEBUG return (context => factory.Create(context, packToCore, unpackFromCore, unpackToCore) as MessagePackSerializer <TObject>); } } }
protected override ExpressionConstruct EmitCreateNewArrayExpression( ExpressionTreeContext context, Type elementType, int length, IEnumerable <ExpressionConstruct> initialElements ) { return(Expression.NewArrayInit(elementType, initialElements.Select(c => c.Expression))); }