80 lines
3.7 KiB
C#
80 lines
3.7 KiB
C#
using System.Reflection;
|
|
|
|
namespace Prefab.Endpoints;
|
|
|
|
/// <summary>
|
|
/// Provides utility methods for generating standardized endpoint names based on type and module information.
|
|
/// </summary>
|
|
/// <remarks>This class is intended for internal use to construct endpoint names that reflect the module and
|
|
/// feature structure of the application. The generated names are typically used for routing, messaging, or service
|
|
/// registration scenarios where consistent naming conventions are required. Endpoint names are constructed using the
|
|
/// namespace or assembly segments of the provided type, followed by the specified endpoint name.</remarks>
|
|
internal static class EndpointName
|
|
{
|
|
/// <summary>
|
|
/// Gets the default name for the specified type parameter.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type for which to retrieve the default name.</typeparam>
|
|
/// <returns>A string containing the default name of the type parameter <typeparamref name="T"/>.</returns>
|
|
public static string For<T>() => For<T>(typeof(T).Name);
|
|
|
|
/// <summary>
|
|
/// Gets the endpoint name for the specified type and endpoint identifier.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type for which to retrieve the endpoint name.</typeparam>
|
|
/// <param name="endpointName">The logical name of the endpoint. Cannot be null or empty.</param>
|
|
/// <returns>A string representing the endpoint name associated with the specified type and endpoint identifier.</returns>
|
|
public static string For<T>(string endpointName) => For(typeof(T), endpointName);
|
|
|
|
/// <summary>
|
|
/// Generates a fully qualified endpoint name by combining the module segments derived from the specified type with
|
|
/// the provided endpoint name.
|
|
/// </summary>
|
|
/// <param name="type">The type from which to resolve module segments. Typically, represents the class or module associated with the
|
|
/// endpoint.</param>
|
|
/// <param name="endpointName">The name of the endpoint to append. Cannot be null, empty, or consist only of white-space characters.</param>
|
|
/// <returns>A string representing the fully qualified endpoint name in the format 'Module.Segment.EndpointName'.</returns>
|
|
/// <exception cref="ArgumentException">Thrown if endpointName is null, empty, or consists only of white-space characters.</exception>
|
|
public static string For(Type type, string endpointName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(endpointName))
|
|
{
|
|
throw new ArgumentException("Endpoint name cannot be null or whitespace.", nameof(endpointName));
|
|
}
|
|
|
|
var segments = ResolveModuleSegments(type);
|
|
return $"{string.Join('.', segments)}.{endpointName}";
|
|
}
|
|
|
|
private static string[] ResolveModuleSegments(MemberInfo type)
|
|
{
|
|
if (type is Type concreteType)
|
|
{
|
|
var namespaceSegments = ExtractNamespaceSegments(concreteType.Namespace);
|
|
if (namespaceSegments.Length > 0)
|
|
{
|
|
return namespaceSegments;
|
|
}
|
|
}
|
|
|
|
var assemblySegments = ExtractNamespaceSegments(type.Module?.Assembly?.GetName().Name);
|
|
return assemblySegments.Length > 0 ? assemblySegments : [type.Name];
|
|
}
|
|
|
|
private static string[] ExtractNamespaceSegments(string? root)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(root))
|
|
{
|
|
return [];
|
|
}
|
|
|
|
var segments = root.Split('.', StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
// Convention: Prefab.<Module>.(App.)<Feature>...
|
|
return segments
|
|
.SkipWhile(segment => string.Equals(segment, "Prefab", StringComparison.Ordinal))
|
|
.Where(segment => !string.Equals(segment, "App", StringComparison.Ordinal))
|
|
.ToArray();
|
|
}
|
|
}
|