|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.ObjectModel;
using System.Reflection;
namespace System.ComponentModel.Design;
/// <summary>
/// DesignerActionList is the abstract base class which control authors inherit from to create a task sheet.
/// Typical usage is to add properties and methods and then implement the abstract
/// GetSortedActionItems method to return an array of DesignerActionItems in the order they are to be displayed.
/// </summary>
public class DesignerActionList
{
public DesignerActionList(IComponent? component) => Component = component;
public virtual bool AutoShow { get; set; }
public IComponent? Component { get; }
public object? GetService(Type serviceType) => Component?.Site?.GetService(serviceType);
public virtual DesignerActionItemCollection GetSortedActionItems()
{
var items = new SortedList<string, DesignerActionItem>();
// we want to ignore the public methods and properties for THIS class (only take the inherited ones)
ReadOnlyCollection<MethodInfo> originalMethods = Array.AsReadOnly(
typeof(DesignerActionList).GetMethods(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public));
ReadOnlyCollection<PropertyInfo> originalProperties = Array.AsReadOnly(
typeof(DesignerActionList).GetProperties(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public));
// Do methods
MethodInfo[] methods = GetType().GetMethods(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public);
foreach (MethodInfo info in methods)
{
if (originalMethods.Contains(info))
{
continue;
}
// Make sure there are only methods that take no parameters
if (info.GetParameters().Length == 0 && !info.IsSpecialName)
{
GetMemberDisplayProperties(info, out string dispName, out string desc, out string cat);
items.Add(info.Name, new DesignerActionMethodItem(this, info.Name, dispName, cat, desc));
}
}
// Do properties
PropertyInfo[] properties = GetType().GetProperties(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public);
foreach (PropertyInfo info in properties)
{
if (originalProperties.Contains(info))
{
continue;
}
GetMemberDisplayProperties(info, out string dispName, out string desc, out string cat);
items.Add(dispName, new DesignerActionPropertyItem(info.Name, dispName, cat, desc));
}
DesignerActionItemCollection returnValue = [.. items.Values];
return returnValue;
}
private static object? GetCustomAttribute(MemberInfo info, Type attributeType)
{
object[] attributes = info.GetCustomAttributes(attributeType, true);
return attributes.Length > 0 ? attributes[0] : null;
}
private static void GetMemberDisplayProperties(MemberInfo info, out string displayName, out string description, out string category)
{
displayName = string.Empty;
description = string.Empty;
category = string.Empty;
if (GetCustomAttribute(info, typeof(DescriptionAttribute)) is DescriptionAttribute descAttr)
{
description = descAttr.Description;
}
if (GetCustomAttribute(info, typeof(DisplayNameAttribute)) is DisplayNameAttribute dispNameAttr)
{
displayName = dispNameAttr.DisplayName;
}
if (GetCustomAttribute(info, typeof(CategoryAttribute)) is CategoryAttribute catAttr)
{
category = catAttr.Category;
}
if (string.IsNullOrEmpty(displayName))
{
displayName = info.Name;
}
}
}
|