mirror of
https://github.com/microsoft/autogen.git
synced 2025-09-09 08:16:09 +00:00
71 lines
3.5 KiB
C#
71 lines
3.5 KiB
C#
![]() |
// 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;
|
||
|
}
|
||
|
}
|