| File: System\ComponentModel\Composition\ReflectionModel\LazyMemberInfo.cs | Web Access |
| Project: src\runtime\src\libraries\System.ComponentModel.Composition\src\System.ComponentModel.Composition.csproj (System.ComponentModel.Composition) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; using System.Linq; using System.Reflection; using Microsoft.Internal; namespace System.ComponentModel.Composition.ReflectionModel { public struct LazyMemberInfo : IEquatable<LazyMemberInfo> { private readonly MemberTypes _memberType; private MemberInfo?[]? _accessors; private readonly Func<MemberInfo[]>? _accessorsCreator; public LazyMemberInfo(MemberInfo member) { Requires.NotNull(member, nameof(member)); EnsureSupportedMemberType(member.MemberType, nameof(member)); _accessorsCreator = null; _memberType = member.MemberType; switch (_memberType) { case MemberTypes.Property: PropertyInfo property = (PropertyInfo)member; if (property == null) { throw new Exception(SR.Diagnostic_InternalExceptionMessage); } _accessors = new MemberInfo?[] { property.GetGetMethod(true), property.GetSetMethod(true) }; break; case MemberTypes.Event: EventInfo event_ = (EventInfo)member; _accessors = new MemberInfo?[] { event_.GetRaiseMethod(true), event_.GetAddMethod(true), event_.GetRemoveMethod(true) }; break; default: _accessors = new MemberInfo[] { member }; break; } } public LazyMemberInfo(MemberTypes memberType, params MemberInfo[] accessors) { EnsureSupportedMemberType(memberType, nameof(memberType)); Requires.NotNull(accessors, nameof(accessors)); string errorMessage; if (!LazyMemberInfo.AreAccessorsValid(memberType, accessors, out errorMessage)) { throw new ArgumentException(errorMessage, nameof(accessors)); } _memberType = memberType; _accessors = accessors; _accessorsCreator = null; } public LazyMemberInfo(MemberTypes memberType, Func<MemberInfo[]> accessorsCreator) { EnsureSupportedMemberType(memberType, nameof(memberType)); Requires.NotNull(accessorsCreator, nameof(accessorsCreator)); _memberType = memberType; _accessors = null; _accessorsCreator = accessorsCreator; } public MemberTypes MemberType { get { return _memberType; } } public MemberInfo[] GetAccessors() { if ((_accessors == null) && (_accessorsCreator != null)) { MemberInfo[] accessors = _accessorsCreator.Invoke(); string errorMessage; if (!LazyMemberInfo.AreAccessorsValid(MemberType, accessors, out errorMessage)) { throw new InvalidOperationException(errorMessage); } _accessors = accessors; } return _accessors!; } public override int GetHashCode() { if (_accessorsCreator != null) { return MemberType.GetHashCode() ^ _accessorsCreator.GetHashCode(); } if (_accessors != null && _accessors[0] is MemberInfo accessor) { return MemberType.GetHashCode() ^ accessor.GetHashCode(); } throw new Exception(SR.Diagnostic_InternalExceptionMessage); } public override bool Equals(object? obj) => obj is LazyMemberInfo other && Equals(other); /// <summary>Indicates whether the current instance is equal to another instance of the same type.</summary> /// <param name="other">An instance to compare with this instance.</param> /// <returns>true if the current instance is equal to the other instance; otherwise, false.</returns> public bool Equals(LazyMemberInfo other) { // Different member types mean different members if (_memberType != other._memberType) { return false; } // if any of the lazy members create accessors in a delay-loaded fashion, we simply compare the creators if ((_accessorsCreator != null) || (other._accessorsCreator != null)) { return object.Equals(_accessorsCreator, other._accessorsCreator); } // we are dealing with explicitly passed accessors in both cases if (_accessors == null || other._accessors == null) { throw new Exception(SR.Diagnostic_InternalExceptionMessage); } return _accessors.SequenceEqual(other._accessors); } public static bool operator ==(LazyMemberInfo left, LazyMemberInfo right) { return left.Equals(right); } public static bool operator !=(LazyMemberInfo left, LazyMemberInfo right) { return !left.Equals(right); } private static void EnsureSupportedMemberType(MemberTypes memberType, string argument) { MemberTypes supportedTypes = MemberTypes.TypeInfo | MemberTypes.NestedType | MemberTypes.Constructor | MemberTypes.Field | MemberTypes.Method | MemberTypes.Property | MemberTypes.Event; Requires.IsInMembertypeSet(memberType, argument, supportedTypes); } private static bool AreAccessorsValid(MemberTypes memberType, MemberInfo[] accessors, out string errorMessage) { errorMessage = string.Empty; if (accessors == null) { errorMessage = SR.LazyMemberInfo_AccessorsNull; return false; } if (accessors.All(accessor => accessor == null)) { errorMessage = SR.LazyMemberInfo_NoAccessors; return false; } switch (memberType) { case MemberTypes.Property: if (accessors.Length != 2) { errorMessage = SR.LazyMemberInfo_InvalidPropertyAccessors_Cardinality; return false; } if (accessors.Where(accessor => (accessor != null) && (accessor.MemberType != MemberTypes.Method)).Any()) { errorMessage = SR.LazyMemberinfo_InvalidPropertyAccessors_AccessorType; return false; } break; case MemberTypes.Event: if (accessors.Length != 3) { errorMessage = SR.LazyMemberInfo_InvalidEventAccessors_Cardinality; return false; } if (accessors.Where(accessor => (accessor != null) && (accessor.MemberType != MemberTypes.Method)).Any()) { errorMessage = SR.LazyMemberinfo_InvalidEventAccessors_AccessorType; return false; } break; default: if ( (accessors.Length != 1) || ((accessors.Length == 1) && (accessors[0].MemberType != memberType))) { errorMessage = SR.Format(SR.LazyMemberInfo_InvalidAccessorOnSimpleMember, memberType); return false; } break; } return true; } } }