/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Microsoft Public License. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Microsoft Public License, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Microsoft Public License. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ using System; using Microsoft; #if !SILVERLIGHT // ComObject #if CODEPLEX_40 using System.Linq.Expressions; #else using Microsoft.Linq.Expressions; #endif using System.Runtime.CompilerServices; #if !CODEPLEX_40 using Microsoft.Runtime.CompilerServices; #endif using System.Security; using System.Security.Permissions; #if CODEPLEX_40 namespace System.Dynamic { #else namespace Microsoft.Scripting { #endif internal sealed class BoundDispEvent : DynamicObject { private object _rcw; private Guid _sourceIid; private int _dispid; internal BoundDispEvent(object rcw, Guid sourceIid, int dispid) { _rcw = rcw; _sourceIid = sourceIid; _dispid = dispid; } /// /// Provides the implementation of performing AddAssign and SubtractAssign binary operations. /// /// The binder provided by the call site. /// The handler for the operation. /// The result of the operation. /// true if the operation is complete, false if the call site should determine behavior. public override bool TryBinaryOperation(BinaryOperationBinder binder, object handler, out object result) { if (binder.Operation == ExpressionType.AddAssign) { result = InPlaceAdd(handler); return true; } if (binder.Operation == ExpressionType.SubtractAssign) { result = InPlaceSubtract(handler); return true; } result = null; return false; } private static void VerifyHandler(object handler) { if (handler is Delegate && handler.GetType() != typeof(Delegate)) { return; // delegate } if (handler is IDynamicMetaObjectProvider) { return; // IDMOP } throw Error.UnsupportedHandlerType(); } /// /// Adds a handler to an event. /// /// The handler to be added. /// The original event with handler added. #if CLR2 [SecurityCritical, SecurityTreatAsSafe] #else [SecuritySafeCritical] #endif private object InPlaceAdd(object handler) { ContractUtils.RequiresNotNull(handler, "handler"); VerifyHandler(handler); // // Demand Full Trust to proceed with the operation. // new PermissionSet(PermissionState.Unrestricted).Demand(); ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, true); comEventSink.AddHandler(_dispid, handler); return this; } /// /// Removes handler from the event. /// /// The handler to be removed. /// The original event with handler removed. #if CLR2 [SecurityCritical, SecurityTreatAsSafe] #else [SecuritySafeCritical] #endif private object InPlaceSubtract(object handler) { ContractUtils.RequiresNotNull(handler, "handler"); VerifyHandler(handler); // // Demand Full Trust to proceed with the operation. // new PermissionSet(PermissionState.Unrestricted).Demand(); ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, false); if (comEventSink != null) { comEventSink.RemoveHandler(_dispid, handler); } return this; } } } #endif