MemberSpecifiedDecorator.cs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #if !NO_RUNTIME
  2. using System;
  3. using ProtoBuf.Meta;
  4. #if FEAT_IKVM
  5. using Type = IKVM.Reflection.Type;
  6. using IKVM.Reflection;
  7. #else
  8. using System.Reflection;
  9. #endif
  10. namespace ProtoBuf.Serializers
  11. {
  12. sealed class MemberSpecifiedDecorator : ProtoDecoratorBase
  13. {
  14. public override Type ExpectedType { get { return Tail.ExpectedType; } }
  15. public override bool RequiresOldValue { get { return Tail.RequiresOldValue; } }
  16. public override bool ReturnsValue { get { return Tail.ReturnsValue; } }
  17. private readonly MethodInfo getSpecified, setSpecified;
  18. public MemberSpecifiedDecorator(MethodInfo getSpecified, MethodInfo setSpecified, IProtoSerializer tail)
  19. : base(tail)
  20. {
  21. if (getSpecified == null && setSpecified == null) throw new InvalidOperationException();
  22. this.getSpecified = getSpecified;
  23. this.setSpecified = setSpecified;
  24. }
  25. #if !FEAT_IKVM
  26. public override void Write(object value, ProtoWriter dest)
  27. {
  28. if(getSpecified == null || (bool)getSpecified.Invoke(value, null))
  29. {
  30. Tail.Write(value, dest);
  31. }
  32. }
  33. public override object Read(object value, ProtoReader source)
  34. {
  35. object result = Tail.Read(value, source);
  36. if (setSpecified != null) setSpecified.Invoke(value, new object[] { true });
  37. return result;
  38. }
  39. #endif
  40. #if FEAT_COMPILER
  41. protected override void EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom)
  42. {
  43. if (getSpecified == null)
  44. {
  45. Tail.EmitWrite(ctx, valueFrom);
  46. return;
  47. }
  48. using (Compiler.Local loc = ctx.GetLocalWithValue(ExpectedType, valueFrom))
  49. {
  50. ctx.LoadAddress(loc, ExpectedType);
  51. ctx.EmitCall(getSpecified);
  52. Compiler.CodeLabel done = ctx.DefineLabel();
  53. ctx.BranchIfFalse(done, false);
  54. Tail.EmitWrite(ctx, loc);
  55. ctx.MarkLabel(done);
  56. }
  57. }
  58. protected override void EmitRead(Compiler.CompilerContext ctx, Compiler.Local valueFrom)
  59. {
  60. if (setSpecified == null)
  61. {
  62. Tail.EmitRead(ctx, valueFrom);
  63. return;
  64. }
  65. using (Compiler.Local loc = ctx.GetLocalWithValue(ExpectedType, valueFrom))
  66. {
  67. Tail.EmitRead(ctx, loc);
  68. ctx.LoadAddress(loc, ExpectedType);
  69. ctx.LoadValue(1); // true
  70. ctx.EmitCall(setSpecified);
  71. }
  72. }
  73. #endif
  74. }
  75. }
  76. #endif