You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取类实现的INotificationHandler<>的泛型参数类型?

Safely Extracting INotificationHandler Generic Arguments

Great question! Using GenericTypeArguments[0] works in simple cases, but it's fragile—it relies on the INotificationHandler<> interfaces being the first generic interfaces implemented by your class. If you ever add another generic interface (or reorder them), this will break unexpectedly.

Here's a much safer approach that explicitly targets the INotificationHandler<> interface, regardless of how many other interfaces your class implements or their order:

using System;
using System.Collections.Generic;
using System.Linq;

public static class TypeExtractor
{
    public static IEnumerable<Type> MagicFunctionToGetTemplateTypesForNotificationHandlerInterface(IEnumerable<Type> typesList)
    {
        // Define the open generic type we're searching for
        var handlerGenericDefinition = typeof(INotificationHandler<>);
        
        foreach (var type in typesList)
        {
            // Filter interfaces to only closed versions of INotificationHandler<>
            var matchingInterfaces = type.GetInterfaces()
                .Where(iface => iface.IsGenericType && 
                                iface.GetGenericTypeDefinition() == handlerGenericDefinition);
            
            foreach (var iface in matchingInterfaces)
            {
                // Extract the single generic argument (INotificationHandler<> only has one)
                var genericArgs = iface.GetGenericArguments();
                if (genericArgs.Length == 1) // Extra safety guard against unexpected interface changes
                {
                    yield return genericArgs[0];
                }
            }
        }
    }
}

Why this is safer:

  • Explicit targeting: We only process interfaces that match the INotificationHandler<> open generic type, so other generic interfaces (like IEnumerable<> or custom ones) won't interfere.
  • Order-agnostic: It doesn't matter if INotificationHandler<> is the first interface or the tenth—we'll find it regardless.
  • Robust to changes: If you modify the class to add more interfaces later, this code won't break silently.
  • Safety check: The extra check for genericArgs.Length == 1 adds a layer of protection in case the INotificationHandler interface ever changes (unlikely, but it's a cheap guardrail).

What's wrong with the original approach?

Suppose you later update your class to:

public class OtherClass : IAnotherGeneric<RandomType>, INotificationHandler<Aggregate>, INotificationHandler<Quote> { /* */ }

Using GetType().GenericTypeArguments[0] would now return RandomType instead of Aggregate—a silent bug that's hard to track down. The safe approach avoids this entirely.

Testing it out

With your original typesList = new[] { typeof(OtherClass) }, calling MagicFunctionToGetTemplateTypesForNotificationHandlerInterface(typesList) will correctly return typeof(Aggregate) and typeof(Quote) (order depends on interface enumeration, but both will be included).

内容的提问来源于stack exchange,提问作者morleyc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 10:32:55