File: Emit\NoPia\CommonEmbeddedEvent.cs
Web Access
Project: src\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using Cci = Microsoft.Cci;
 
namespace Microsoft.CodeAnalysis.Emit.NoPia
{
    internal abstract partial class EmbeddedTypesManager<
        TPEModuleBuilder,
        TModuleCompilationState,
        TEmbeddedTypesManager,
        TSyntaxNode,
        TAttributeData,
        TSymbol,
        TAssemblySymbol,
        TNamedTypeSymbol,
        TFieldSymbol,
        TMethodSymbol,
        TEventSymbol,
        TPropertySymbol,
        TParameterSymbol,
        TTypeParameterSymbol,
        TEmbeddedType,
        TEmbeddedField,
        TEmbeddedMethod,
        TEmbeddedEvent,
        TEmbeddedProperty,
        TEmbeddedParameter,
        TEmbeddedTypeParameter>
    {
        internal abstract class CommonEmbeddedEvent : CommonEmbeddedMember<TEventSymbol>, Cci.IEventDefinition
        {
            private readonly TEmbeddedMethod _adder;
            private readonly TEmbeddedMethod _remover;
            private readonly TEmbeddedMethod _caller;
 
            private int _isUsedForComAwareEventBinding;
 
            protected CommonEmbeddedEvent(TEventSymbol underlyingEvent, TEmbeddedMethod adder, TEmbeddedMethod remover, TEmbeddedMethod caller) :
                base(underlyingEvent)
            {
                Debug.Assert(adder != null || remover != null);
 
                _adder = adder;
                _remover = remover;
                _caller = caller;
            }
 
            internal override TEmbeddedTypesManager TypeManager
            {
                get
                {
                    return AnAccessor.TypeManager;
                }
            }
 
            protected abstract bool IsRuntimeSpecial { get; }
            protected abstract bool IsSpecialName { get; }
            protected abstract Cci.ITypeReference GetType(TPEModuleBuilder moduleBuilder, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics);
            protected abstract TEmbeddedType ContainingType { get; }
            protected abstract Cci.TypeMemberVisibility Visibility { get; }
            protected abstract string Name { get; }
 
            public TEventSymbol UnderlyingEvent
            {
                get
                {
                    return this.UnderlyingSymbol;
                }
            }
 
            protected abstract void EmbedCorrespondingComEventInterfaceMethodInternal(TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics, bool isUsedForComAwareEventBinding);
 
            internal void EmbedCorrespondingComEventInterfaceMethod(TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics, bool isUsedForComAwareEventBinding)
            {
                if (_isUsedForComAwareEventBinding == 0 &&
                    (!isUsedForComAwareEventBinding ||
                     Interlocked.CompareExchange(ref _isUsedForComAwareEventBinding, 1, 0) == 0))
                {
                    Debug.Assert(!isUsedForComAwareEventBinding || _isUsedForComAwareEventBinding != 0);
 
                    EmbedCorrespondingComEventInterfaceMethodInternal(syntaxNodeOpt, diagnostics, isUsedForComAwareEventBinding);
                }
 
                Debug.Assert(!isUsedForComAwareEventBinding || _isUsedForComAwareEventBinding != 0);
            }
 
            Cci.IMethodReference Cci.IEventDefinition.Adder
            {
                get { return _adder; }
            }
 
            Cci.IMethodReference Cci.IEventDefinition.Remover
            {
                get { return _remover; }
            }
 
            Cci.IMethodReference Cci.IEventDefinition.Caller
            {
                get { return _caller; }
            }
 
            IEnumerable<Cci.IMethodReference> Cci.IEventDefinition.GetAccessors(EmitContext context)
            {
                if (_adder != null)
                {
                    yield return _adder;
                }
 
                if (_remover != null)
                {
                    yield return _remover;
                }
 
                if (_caller != null)
                {
                    yield return _caller;
                }
            }
 
            bool Cci.IEventDefinition.IsRuntimeSpecial
            {
                get
                {
                    return IsRuntimeSpecial;
                }
            }
 
            bool Cci.IEventDefinition.IsSpecialName
            {
                get
                {
                    return IsSpecialName;
                }
            }
 
            Cci.ITypeReference Cci.IEventDefinition.GetType(EmitContext context)
            {
                return GetType((TPEModuleBuilder)context.Module, (TSyntaxNode)context.SyntaxNode, context.Diagnostics);
            }
 
            protected TEmbeddedMethod AnAccessor
            {
                get
                {
                    return _adder ?? _remover;
                }
            }
 
            Cci.ITypeDefinition Cci.ITypeDefinitionMember.ContainingTypeDefinition
            {
                get { return ContainingType; }
            }
 
            Cci.TypeMemberVisibility Cci.ITypeDefinitionMember.Visibility
            {
                get
                {
                    return Visibility;
                }
            }
 
            Cci.ITypeReference Cci.ITypeMemberReference.GetContainingType(EmitContext context)
            {
                return ContainingType;
            }
 
            void Cci.IReference.Dispatch(Cci.MetadataVisitor visitor)
            {
                visitor.Visit((Cci.IEventDefinition)this);
            }
 
            Cci.IDefinition Cci.IReference.AsDefinition(EmitContext context)
            {
                return this;
            }
 
            string Cci.INamedEntity.Name
            {
                get
                {
                    return Name;
                }
            }
        }
    }
}