/Microsoft.Dynamic/BoundDispEvent.cs

https://bitbucket.org/stefanrusek/xronos · C# · 116 lines · 67 code · 18 blank · 31 comment · 10 complexity · 17d975dec0331aaca03cb64dc0cdc164 MD5 · raw file

  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System; using Microsoft;
  16. #if !SILVERLIGHT // ComObject
  17. #if CODEPLEX_40
  18. using System.Linq.Expressions;
  19. #else
  20. using Microsoft.Linq.Expressions;
  21. #endif
  22. using System.Runtime.CompilerServices;
  23. #if !CODEPLEX_40
  24. using Microsoft.Runtime.CompilerServices;
  25. #endif
  26. #if CODEPLEX_40
  27. namespace System.Dynamic {
  28. #else
  29. namespace Microsoft.Scripting {
  30. #endif
  31. internal sealed class BoundDispEvent : DynamicObject {
  32. private object _rcw;
  33. private Guid _sourceIid;
  34. private int _dispid;
  35. internal BoundDispEvent(object rcw, Guid sourceIid, int dispid) {
  36. _rcw = rcw;
  37. _sourceIid = sourceIid;
  38. _dispid = dispid;
  39. }
  40. /// <summary>
  41. /// Provides the implementation of performing AddAssign and SubtractAssign binary operations.
  42. /// </summary>
  43. /// <param name="binder">The binder provided by the call site.</param>
  44. /// <param name="handler">The handler for the operation.</param>
  45. /// <param name="result">The result of the operation.</param>
  46. /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
  47. public override bool TryBinaryOperation(BinaryOperationBinder binder, object handler, out object result) {
  48. if (binder.Operation == ExpressionType.AddAssign) {
  49. result = InPlaceAdd(handler);
  50. return true;
  51. }
  52. if (binder.Operation == ExpressionType.SubtractAssign) {
  53. result = InPlaceSubtract(handler);
  54. return true;
  55. }
  56. result = null;
  57. return false;
  58. }
  59. private static void VerifyHandler(object handler) {
  60. if (handler is Delegate && handler.GetType() != typeof(Delegate)) {
  61. return; // delegate
  62. }
  63. if (handler is IDynamicMetaObjectProvider) {
  64. return; // IDMOP
  65. }
  66. throw Error.UnsupportedHandlerType();
  67. }
  68. /// <summary>
  69. /// Adds a handler to an event.
  70. /// </summary>
  71. /// <param name="handler">The handler to be added.</param>
  72. /// <returns>The original event with handler added.</returns>
  73. [SpecialName]
  74. public object InPlaceAdd(object handler) {
  75. ContractUtils.RequiresNotNull(handler, "handler");
  76. VerifyHandler(handler);
  77. ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, true);
  78. comEventSink.AddHandler(_dispid, handler);
  79. return this;
  80. }
  81. /// <summary>
  82. /// Removes handler from the event.
  83. /// </summary>
  84. /// <param name="handler">The handler to be removed.</param>
  85. /// <returns>The original event with handler removed.</returns>
  86. [SpecialName]
  87. public object InPlaceSubtract(object handler) {
  88. ContractUtils.RequiresNotNull(handler, "handler");
  89. VerifyHandler(handler);
  90. ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, false);
  91. if (comEventSink != null) {
  92. comEventSink.RemoveHandler(_dispid, handler);
  93. }
  94. return this;
  95. }
  96. }
  97. }
  98. #endif