/* ****************************************************************************
*
* 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
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using ComTypes = System.Runtime.InteropServices.ComTypes;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
///
/// This class implements an event sink for a particular RCW.
/// Unlike the implementation of events in TlbImp'd assemblies,
/// we will create only one event sink per RCW (theoretically RCW might have
/// several ComEventSink evenk sinks - but all these implement different source intefaces).
/// Each ComEventSink contains a list of ComEventSinkMethod objects - which represent
/// a single method on the source interface an a multicast delegate to redirect
/// the calls. Notice that we are chaining multicast delegates so that same
/// ComEventSinkMedhod can invoke multiple event handlers).
///
/// ComEventSink implements an IDisposable pattern to Unadvise from the connection point.
/// Typically, when RCW is finalized the corresponding Dispose will be triggered by
/// ComEventSinksContainer finalizer. Notice that lifetime of ComEventSinksContainer
/// is bound to the lifetime of the RCW.
///
internal sealed class ComEventSink : MarshalByRefObject, IReflect, IDisposable {
#region private fields
private Guid _sourceIid;
private ComTypes.IConnectionPoint _connectionPoint;
private int _adviseCookie;
private List _comEventSinkMethods;
private object _lockObject = new object(); // We cannot lock on ComEventSink since it causes a DoNotLockOnObjectsWithWeakIdentity warning
#endregion
#region private classes
///
/// Contains a methods DISPID (in a string formatted of "[DISPID=N]"
/// and a chained list of delegates to invoke
///
private class ComEventSinkMethod {
public string _name;
public Func