/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ #if !SILVERLIGHT // ComObject using System.Collections.Generic; using System.Runtime.InteropServices; namespace System.Management.Automation.ComInterop { /// /// ComEventSinksContainer is just a regular list with a finalizer. /// This list is usually attached as a custom data for RCW object and /// is finalized whenever RCW is finalized. /// internal class ComEventSinksContainer : List, IDisposable { private ComEventSinksContainer() { } private static readonly object s_comObjectEventSinksKey = new object(); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")] public static ComEventSinksContainer FromRuntimeCallableWrapper(object rcw, bool createIfNotFound) { // !!! Marshal.Get/SetComObjectData has a LinkDemand for UnmanagedCode which will turn into // a full demand. We need to avoid this by making this method SecurityCritical object data = Marshal.GetComObjectData(rcw, s_comObjectEventSinksKey); if (data != null || createIfNotFound == false) { return (ComEventSinksContainer)data; } lock (s_comObjectEventSinksKey) { data = Marshal.GetComObjectData(rcw, s_comObjectEventSinksKey); if (data != null) { return (ComEventSinksContainer)data; } ComEventSinksContainer comEventSinks = new ComEventSinksContainer(); if (!Marshal.SetComObjectData(rcw, s_comObjectEventSinksKey, comEventSinks)) { throw Error.SetComObjectDataFailed(); } return comEventSinks; } } #region IDisposable Members public void Dispose() { DisposeAll(); GC.SuppressFinalize(this); } #endregion private void DisposeAll() { foreach (ComEventSink sink in this) { sink.Dispose(); } } ~ComEventSinksContainer() { DisposeAll(); } } } #endif