File: Symbols\AnonymousTypes\PublicSymbols\AnonymousType.TypePublicSymbol.cs
Web Access
Project: src\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp)
// 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.
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal sealed partial class AnonymousTypeManager
    {
        /// <summary>
        /// Represents an anonymous type 'public' symbol which is used in binding and lowering.
        /// In emit phase it is being substituted with implementation symbol.
        /// </summary>
        internal sealed class AnonymousTypePublicSymbol : AnonymousTypeOrDelegatePublicSymbol
        {
            private readonly ImmutableArray<Symbol> _members;
 
            /// <summary> Properties defined in the type </summary>
            internal readonly ImmutableArray<AnonymousTypePropertySymbol> Properties;
 
            /// <summary> Maps member names to symbol(s) </summary>
            private readonly MultiDictionary<string, Symbol> _nameToSymbols = new MultiDictionary<string, Symbol>();
 
            internal AnonymousTypePublicSymbol(AnonymousTypeManager manager, AnonymousTypeDescriptor typeDescr) :
                base(manager, typeDescr)
            {
                typeDescr.AssertIsGood();
 
                var fields = typeDescr.Fields;
                var properties = fields.SelectAsArray((field, i, type) => new AnonymousTypePropertySymbol(type, field, i), this);
 
                //  members
                int membersCount = fields.Length * 2 + 1;
                var members = ArrayBuilder<Symbol>.GetInstance(membersCount);
 
                foreach (var property in properties)
                {
                    // Property related symbols
                    members.Add(property);
                    members.Add(property.GetMethod);
                }
 
                this.Properties = properties;
 
                // Add a constructor
                members.Add(new AnonymousTypeConstructorSymbol(this, properties));
                _members = members.ToImmutableAndFree();
                Debug.Assert(membersCount == _members.Length);
 
                //  fill nameToSymbols map
                foreach (var symbol in _members)
                {
                    _nameToSymbols.Add(symbol.Name, symbol);
                }
            }
 
            internal override NamedTypeSymbol MapToImplementationSymbol()
            {
                return Manager.ConstructAnonymousTypeImplementationSymbol(this);
            }
 
            internal override AnonymousTypeOrDelegatePublicSymbol SubstituteTypes(AbstractTypeMap map)
            {
                var oldFieldTypes = TypeDescriptor.Fields.SelectAsArray(f => f.TypeWithAnnotations);
                var newFieldTypes = map.SubstituteTypes(oldFieldTypes);
                return (oldFieldTypes == newFieldTypes) ?
                    this :
                    new AnonymousTypePublicSymbol(Manager, TypeDescriptor.WithNewFieldsTypes(newFieldTypes));
            }
 
            public override TypeKind TypeKind
            {
                get { return TypeKind.Class; }
            }
 
            internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics => Manager.System_Object;
 
            public override ImmutableArray<Symbol> GetMembers()
            {
                return _members;
            }
 
            public override ImmutableArray<Symbol> GetMembers(string name)
            {
                var symbols = _nameToSymbols[name];
                var builder = ArrayBuilder<Symbol>.GetInstance(symbols.Count);
                foreach (var symbol in symbols)
                {
                    builder.Add(symbol);
                }
 
                return builder.ToImmutableAndFree();
            }
 
            public override IEnumerable<string> MemberNames
            {
                get { return _nameToSymbols.Keys; }
            }
 
            public override bool IsImplicitlyDeclared
            {
                get { return false; }
            }
 
            public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
            {
                get
                {
                    return GetDeclaringSyntaxReferenceHelper<AnonymousObjectCreationExpressionSyntax>(this.Locations);
                }
            }
 
            internal override bool Equals(TypeSymbol t2, TypeCompareKind comparison)
            {
                if (ReferenceEquals(this, t2))
                {
                    return true;
                }
 
                var other = t2 as AnonymousTypePublicSymbol;
                return other is { } && this.TypeDescriptor.Equals(other.TypeDescriptor, comparison);
            }
 
            public override int GetHashCode()
            {
                return this.TypeDescriptor.GetHashCode();
            }
        }
    }
}