| File: System\ComponentModel\Design\PropertyTabAttribute.cs | Web Access |
| Project: src\runtime\src\libraries\System.ComponentModel.TypeConverter\src\System.ComponentModel.TypeConverter.csproj (System.ComponentModel.TypeConverter) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.ComponentModel { /// <summary> /// Identifies the property tab or tabs that should be displayed for the /// specified class or classes. /// </summary> [AttributeUsage(AttributeTargets.All)] public class PropertyTabAttribute : Attribute { private Type[]? _tabClasses; private string[]? _tabClassNames; /// <summary> /// Basic constructor that creates a PropertyTabAttribute. Use this ctor to derive from this /// attribute and specify multiple tab types by calling InitializeArrays. /// </summary> public PropertyTabAttribute() { TabScopes = Array.Empty<PropertyTabScope>(); _tabClassNames = Array.Empty<string>(); } /// <summary> /// Basic constructor that creates a property tab attribute that will create a tab /// of the specified type. /// </summary> public PropertyTabAttribute(Type tabClass) : this(tabClass, PropertyTabScope.Component) { } /// <summary> /// Basic constructor that creates a property tab attribute that will create a tab /// of the specified type. /// </summary> public PropertyTabAttribute( // Using PublicParameterlessConstructor to preserve the type. See https://github.com/mono/linker/issues/1878 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string tabClassName) : this(tabClassName, PropertyTabScope.Component) { } /// <summary> /// Basic constructor that creates a property tab attribute that will create a tab /// of the specified type. /// </summary> public PropertyTabAttribute(Type tabClass, PropertyTabScope tabScope) { _tabClasses = new Type[] { tabClass }; if (tabScope < PropertyTabScope.Document) { throw new ArgumentException(SR.PropertyTabAttributeBadPropertyTabScope, nameof(tabScope)); } TabScopes = new PropertyTabScope[] { tabScope }; } /// <summary> /// Basic constructor that creates a property tab attribute that will create a tab /// of the specified type. /// </summary> public PropertyTabAttribute( // Using PublicParameterlessConstructor to preserve the type. See https://github.com/mono/linker/issues/1878 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string tabClassName, PropertyTabScope tabScope) { _tabClassNames = new string[] { tabClassName }; if (tabScope < PropertyTabScope.Document) { throw new ArgumentException(SR.PropertyTabAttributeBadPropertyTabScope, nameof(tabScope)); } TabScopes = new PropertyTabScope[] { tabScope }; } /// <summary> /// Gets the types of tab that this attribute specifies. /// </summary> public Type[] TabClasses { get { if (_tabClasses == null && _tabClassNames != null) { InitializeTabClasses(); } return _tabClasses!; } } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The APIs that specify _tabClassNames are either marked with DynamicallyAccessedMembers or RequiresUnreferencedCode.")] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2057:TypeGetType", Justification = "The APIs that specify _tabClassNames are either marked with DynamicallyAccessedMembers or RequiresUnreferencedCode.")] [MemberNotNull(nameof(_tabClasses))] private void InitializeTabClasses() { Debug.Assert(_tabClassNames != null); _tabClasses = new Type[_tabClassNames.Length]; for (int i = 0; i < _tabClassNames.Length; i++) { int commaIndex = _tabClassNames[i].IndexOf(','); string? className; string? assemblyName = null; if (commaIndex != -1) { className = _tabClassNames[i].AsSpan(0, commaIndex).Trim().ToString(); assemblyName = _tabClassNames[i].AsSpan(commaIndex + 1).Trim().ToString(); } else { className = _tabClassNames[i]; } _tabClasses[i] = Type.GetType(className, false)!; if (_tabClasses[i] == null) { if (assemblyName != null) { Assembly a = Assembly.Load(assemblyName); if (a != null) { _tabClasses[i] = a.GetType(className, true)!; } } else { throw new TypeLoadException(SR.Format(SR.PropertyTabAttributeTypeLoadException, className)); } } } } protected string[]? TabClassNames => (string[]?)_tabClassNames?.Clone(); /// <summary> /// Gets the scopes of tabs for this System.ComponentModel.Design.PropertyTabAttribute, from System.ComponentModel.Design.PropertyTabScope. /// </summary> public PropertyTabScope[] TabScopes { get; private set; } public override bool Equals([NotNullWhen(true)] object? other) => Equals(other as PropertyTabAttribute); public bool Equals([NotNullWhen(true)] PropertyTabAttribute? other) { if (other is null) return false; if (ReferenceEquals(this, other)) return true; if (other.TabClasses.Length != TabClasses.Length || other.TabScopes.Length != TabScopes.Length) return false; for (int i = 0; i < TabClasses.Length; i++) { if (TabClasses[i] != other.TabClasses[i] || TabScopes[i] != other.TabScopes[i]) return false; } return true; } /// <summary> /// Returns the hashcode for this object. /// </summary> public override int GetHashCode() => base.GetHashCode(); /// <summary> /// Utiliity function to set the types of tab classes this PropertyTabAttribute specifies. /// </summary> [RequiresUnreferencedCode("The Types referenced by tabClassNames may be trimmed.")] protected void InitializeArrays(string[]? tabClassNames, PropertyTabScope[]? tabScopes) { InitializeArrays(tabClassNames, null, tabScopes); } /// <summary> /// Utiliity function to set the types of tab classes this PropertyTabAttribute specifies. /// </summary> protected void InitializeArrays(Type[]? tabClasses, PropertyTabScope[]? tabScopes) { InitializeArrays(null, tabClasses, tabScopes); } private void InitializeArrays(string[]? tabClassNames, Type[]? tabClasses, PropertyTabScope[]? tabScopes) { if (tabClasses != null) { if (tabScopes != null && tabClasses.Length != tabScopes.Length) { throw new ArgumentException(SR.PropertyTabAttributeArrayLengthMismatch); } _tabClasses = (Type[])tabClasses.Clone(); } else if (tabClassNames != null) { if (tabScopes != null && tabClassNames.Length != tabScopes.Length) { throw new ArgumentException(SR.PropertyTabAttributeArrayLengthMismatch); } _tabClassNames = (string[])tabClassNames.Clone(); _tabClasses = null; } else if (_tabClasses == null && _tabClassNames == null) { throw new ArgumentException(SR.PropertyTabAttributeParamsBothNull); } if (tabScopes != null) { for (int i = 0; i < tabScopes.Length; i++) { if (tabScopes[i] < PropertyTabScope.Document) { throw new ArgumentException(SR.PropertyTabAttributeBadPropertyTabScope); } } TabScopes = (PropertyTabScope[])tabScopes.Clone(); } else { TabScopes = new PropertyTabScope[tabClasses!.Length]; for (int i = 0; i < TabScopes.Length; i++) { TabScopes[i] = PropertyTabScope.Component; } } } } }