|
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // ReflectionHelper.cs
- using System.Reflection;
- using Google.Protobuf;
- using Google.Protobuf.Reflection;
- using Microsoft.AutoGen.Contracts;
- using Microsoft.AutoGen.Core;
-
- namespace Microsoft.AutoGen.RuntimeGateway.Grpc.Tests;
- public sealed class ReflectionHelper
- {
- public static bool IsSubclassOfGeneric(Type type, Type genericBaseType)
- {
- while (type != null && type != typeof(object))
- {
- if (genericBaseType == (type.IsGenericType ? type.GetGenericTypeDefinition() : type))
- {
- return true;
- }
- if (type.BaseType == null)
- {
- return false;
- }
- type = type.BaseType;
- }
- return false;
- }
- public static AgentsMetadata GetAgentsMetadata(params Assembly[] assemblies)
- {
- var interfaceType = typeof(IMessage);
- var pairs = assemblies
- .SelectMany(assembly => assembly.GetTypes())
- .Where(type => interfaceType.IsAssignableFrom(type) && type.IsClass && !type.IsAbstract)
- .Select(t => (t, GetMessageDescriptor(t)));
-
- var descriptors = pairs.Select(t => t.Item2);
- var typeRegistry = TypeRegistry.FromMessages(descriptors);
- var types = pairs.ToDictionary(item => item.Item2?.FullName ?? "", item => item.t);
-
- var eventsMap = assemblies
- .SelectMany(assembly => assembly.GetTypes())
- .Where(type => IsSubclassOfGeneric(type, typeof(BaseAgent)) && !type.IsAbstract)
- .Select(t => (t, t.GetInterfaces()
- .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IHandle<>))
- .Select(i => GetMessageDescriptor(i.GetGenericArguments().First())?.FullName ?? "").ToHashSet()))
- .ToDictionary(item => item.t, item => item.Item2);
- var topicsMap = assemblies
- .SelectMany(assembly => assembly.GetTypes())
- .Where(type => IsSubclassOfGeneric(type, typeof(BaseAgent)) && !type.IsAbstract)
- .Select(t => (t, t.GetCustomAttributes<TypeSubscriptionAttribute>().Select(a => a.Topic).ToHashSet()))
- .ToDictionary(item => item.t, item => item.Item2);
- var topicsPrefixMap = assemblies
- .SelectMany(assembly => assembly.GetTypes())
- .Where(type => IsSubclassOfGeneric(type, typeof(BaseAgent)) && !type.IsAbstract)
- .Select(t => (t, t.GetCustomAttributes<TypePrefixSubscriptionAttribute>().Select(a => a.Topic).ToHashSet()))
- .ToDictionary(item => item.t, item => item.Item2);
- return new AgentsMetadata(typeRegistry, types, eventsMap, topicsMap, topicsPrefixMap);
- }
-
- /// <summary>
- /// Gets the message descriptor for the specified type.
- /// </summary>
- /// <param name="type">The type to get the message descriptor for.</param>
- /// <returns>The message descriptor if found; otherwise, <c>null</c>.</returns>
- public static MessageDescriptor? GetMessageDescriptor(Type type)
- {
- var property = type.GetProperty("Descriptor", BindingFlags.Static | BindingFlags.Public);
- return property?.GetValue(null) as MessageDescriptor;
- }
- }
|