/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
#if !SILVERLIGHT // ComObject
#if !CLR2
using System.Linq.Expressions;
#else
using Microsoft.Scripting.Ast;
#endif
using System.Dynamic;
//using Microsoft.Scripting.Utils;
namespace System.Management.Automation.ComInterop
{
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
}
if (handler is DispCallable)
{
return;
}
throw Error.UnsupportedHandlerType();
}
///
/// Adds a handler to an event.
///
/// The handler to be added.
/// The original event with handler added.
private object InPlaceAdd(object handler)
{
VerifyHandler(handler);
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.
private object InPlaceSubtract(object handler)
{
VerifyHandler(handler);
ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, false);
if (comEventSink != null)
{
comEventSink.RemoveHandler(_dispid, handler);
}
return this;
}
}
}
#endif