Table of Contents

TypeDecoratorExtensions Class

Definition

Namespace
Cuemon
Assemblies
Cuemon.Core.dll
Source
src/Cuemon.Core/Extensions/TypeDecoratorExtensions.cs

Extension methods for the Type class hidden behind the IDecorator<T> interface.

public static class TypeDecoratorExtensions
Inheritance
TypeDecoratorExtensions

Examples

TypeDecoratorExtensions provides extension methods on Decorator.Enclose for deep reflection inspection of .NET types, including member enumeration, interface detection, attribute checking, and circular-reference detection. This example wraps AuditedOrder (annotated with [DataContract]) and calls GetAllProperties, GetAllFields, GetAllEvents, and GetAllMethods to enumerate members across the full hierarchy including its base TrackedEntity. It also uses predicate methods like HasTypes (for FileStream → Stream), HasInterfaces, HasAttribute, HasEnumerableImplementation, IsNullable, and HasAnonymousCharacteristics to classify type capabilities. Console output includes sorted member names, boolean capability flags, default values such as 00000000-0000-0000-0000-000000000000 for Guid, friendly type names like IList<String>, and circular-reference detection results for a LinkedNode with a self-referencing loop.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Cuemon;

namespace Contoso.Reflection;

public sealed class TypeDecoratorExtensionsExample
{
    public static void Run()
    {
        var orderType = Decorator.Enclose(typeof(AuditedOrder));
        var streamType = Decorator.Enclose(typeof(Stream));

        var propertyNames = orderType.GetAllProperties().Select(property => property.Name).OrderBy(name => name).ToArray();
        var fieldNames = orderType.GetAllFields().Select(field => field.Name).OrderBy(name => name).ToArray();
        var eventNames = orderType.GetAllEvents().Select(@event => @event.Name).OrderBy(name => name).ToArray();
        var methodNames = orderType
            .GetAllMethods()
            .Where(method => method.DeclaringType == typeof(AuditedOrder) && !method.IsSpecialName)
            .Select(method => method.Name)
            .Distinct()
            .OrderBy(name => name)
            .ToArray();
        var orderOnlyProperties = orderType.GetRuntimePropertiesExceptOf<TrackedEntity>().Select(property => property.Name).OrderBy(name => name).ToArray();

        bool hasTypes = Decorator.Enclose(typeof(FileStream)).HasTypes(typeof(Stream));
        bool hasInterfaces = Decorator.Enclose(typeof(List<>)).HasInterfaces(typeof(IEnumerable<>));
        bool hasAttribute = orderType.HasAttribute(typeof(DataContractAttribute), typeof(DataMemberAttribute));
        bool hasComparable = Decorator.Enclose(typeof(string)).HasComparableImplementation();
        bool hasComparer = Decorator.Enclose(typeof(StringComparer)).HasComparerImplementation();
        bool hasDictionary = Decorator.Enclose(typeof(ReadOnlyDictionary<int, string>)).HasDictionaryImplementation();
        bool hasEqualityComparer = Decorator.Enclose(typeof(StringComparer)).HasEqualityComparerImplementation();
        bool hasEnumerable = Decorator.Enclose(typeof(ConcurrentBag<int>)).HasEnumerableImplementation();
        bool hasKeyValuePair = Decorator.Enclose(typeof(KeyValuePair<string, int>)).HasKeyValuePairImplementation();
        bool isNullable = Decorator.Enclose(typeof(int?)).IsNullable();
        bool hasAnonymousCharacteristics = Decorator.Enclose(new { ReferenceNumber = "PO-42" }.GetType()).HasAnonymousCharacteristics();
        bool hasDefaultCtor = Decorator.Enclose(typeof(MemoryStream)).HasDefaultConstructor();
        bool isComplex = streamType.IsComplex();

        object defaultValue = Decorator.Enclose(typeof(Guid)).GetDefaultValue();
        string friendlyName = Decorator.Enclose(typeof(IList<string>)).ToFriendlyName();
        MethodBase publishMethod = orderType.MatchMember(nameof(AuditedOrder.Publish));

        bool inheritedIncludesObject = streamType.GetInheritedTypes().Contains(typeof(object));
        bool derivedIncludesMemoryStream = streamType.GetDerivedTypes().Contains(typeof(MemoryStream));
        bool hierarchyIncludesFileStream = streamType.GetHierarchyTypes().Contains(typeof(FileStream));

        var loop = LinkedNode.CreateLoop();
        bool hasCircularReference = Decorator.Enclose(typeof(LinkedNode)).HasCircularReference(loop, maxDepth: 1);

        Console.WriteLine(string.Join(", ", propertyNames));
        Console.WriteLine(string.Join(", ", fieldNames));
        Console.WriteLine(string.Join(", ", eventNames));
        Console.WriteLine(string.Join(", ", methodNames));
        Console.WriteLine(string.Join(", ", orderOnlyProperties));
        Console.WriteLine($"{hasTypes}, {hasInterfaces}, {hasAttribute}");
        Console.WriteLine($"{hasComparable}, {hasComparer}, {hasDictionary}, {hasEqualityComparer}, {hasEnumerable}, {hasKeyValuePair}");
        Console.WriteLine($"{isNullable}, {hasAnonymousCharacteristics}, {hasDefaultCtor}, {isComplex}");
        Console.WriteLine(defaultValue);
        Console.WriteLine(friendlyName);
        Console.WriteLine(publishMethod.Name);
        Console.WriteLine($"{inheritedIncludesObject}, {derivedIncludesMemoryStream}, {hierarchyIncludesFileStream}, {hasCircularReference}");
    }
}

[DataContract]
public sealed class AuditedOrder : TrackedEntity
{
    public string PublicNote;

    [DataMember]
    public string ReferenceNumber { get; set; } = string.Empty;

    public string Status { get; set; } = string.Empty;

    public event EventHandler Published;

    public void Publish()
    {
        Published?.Invoke(this, EventArgs.Empty);
    }
}

public abstract class TrackedEntity
{
    public DateTime CreatedAt { get; set; }
}

public sealed class LinkedNode
{
    public LinkedNode Next { get; set; }

    public static LinkedNode CreateLoop()
    {
        var node = new LinkedNode();
        node.Next = node;
        return node;
    }
}

Methods

Name Description
GetAllEvents(IDecorator<Type>, Action<MemberReflectionOptions>)

Retrieves a collection that represents all events defined on the enclosed Type of the specified decorator and its inheritance chain.

GetAllFields(IDecorator<Type>, Action<MemberReflectionOptions>)

Retrieves a collection that represents all fields defined on the enclosed Type of the specified decorator and its inheritance chain.

GetAllMethods(IDecorator<Type>, Action<MemberReflectionOptions>)

Retrieves a collection that represents all methods defined on the enclosed Type of the specified decorator and its inheritance chain.

GetAllProperties(IDecorator<Type>, Action<MemberReflectionOptions>)

Retrieves a collection that represents all properties defined on the enclosed Type of the specified decorator and its inheritance chain.

GetDefaultValue(IDecorator<Type>)

Gets the default value from the underlying Type of the decorator.

GetDerivedTypes(IDecorator<Type>, params Assembly[])

Gets a collection (self-to-derived) of derived / descendant types from the underlying Type of the decorator.

GetHierarchyTypes(IDecorator<Type>, params Assembly[])

Gets a collection (inherited-to-self-to-derived) of inherited / ancestor and derived / descendant types from the underlying Type of the decorator.

GetInheritedTypes(IDecorator<Type>)

Gets a collection (inherited-to-self) of inherited / ancestor types from the underlying Type of the decorator.

GetRuntimePropertiesExceptOf<T>(IDecorator<Type>)

Retrieves a collection that represents all the properties defined on the enclosed Type of the decorator except those defined on T.

HasAnonymousCharacteristics(IDecorator<Type>)

Determines whether the underlying Type of the decorator suggest an anonymous implementation (be that in a form of a type, delegate or lambda expression).

HasAttribute(IDecorator<Type>, params Type[])

Determines whether the underlying Type of the decorator implements one or more of the specified attributeTypes.

HasCircularReference(IDecorator<Type>, object, int, Func<object, PropertyInfo, object>)

Determines whether the specified source (which type must be the same as the underlying Type of the decorator) has a circular reference.

HasComparableImplementation(IDecorator<Type>)

Determines whether the underlying Type of the decorator implements either IComparable or IComparable<T>.

HasComparerImplementation(IDecorator<Type>)

Determines whether the underlying Type of the decorator implements either IComparer or IComparer<T>.

HasDefaultConstructor(IDecorator<Type>)

Determines whether the underlying Type of the decorator has a default constructor.

HasDictionaryImplementation(IDecorator<Type>)

Determines whether the underlying Type of the decorator implements either IDictionary, IDictionary<TKey, TValue> or IReadOnlyDictionary<TKey, TValue>.

HasEnumerableImplementation(IDecorator<Type>)

Determines whether the underlying Type of the decorator implements either IEnumerable or IEnumerable<T>.

HasEqualityComparerImplementation(IDecorator<Type>)

Determines whether the underlying Type of the decorator implements either IEqualityComparer or IEqualityComparer<T>.

HasInterfaces(IDecorator<Type>, params Type[])

Determines whether the underlying Type of the decorator implements one or more of the specified interfaceTypes.

HasKeyValuePairImplementation(IDecorator<Type>)

Determines whether the underlying Type of the decorator implements either DictionaryEntry or KeyValuePair<TKey, TValue>.

HasTypes(IDecorator<Type>, params Type[])

Determines whether the enclosed Type of the decorator contains one or more of the specified types.

IsComplex(IDecorator<Type>)

Determines whether the underlying Type of the decorator is considered complex in its nature.

IsNullable(IDecorator<Type>)

Determines whether the underlying Type of the decorator is a nullable ValueType.

MatchMember(IDecorator<Type>, string, Action<MethodBaseOptions>)

Conduct a search for memberName using the specified setup on the underlying Type of the decorator.

ToFriendlyName(IDecorator<Type>, Action<TypeNameOptions>)

Returns a human-readable string that represents the underlying Type of the decorator.

See Also