Как определить, реализует ли тип интерфейс с отражением C #

В дополнение к вашему комментарию к ответу Marnix вы можете добиться того, чего хотите, используя немного отражения.

В приведенном ниже примере метод неограниченного использования Foo использует отражение для обработки вызовов на соответствующий ограниченный метод - либо FooWithStruct, либо FooWithClass. По соображениям производительности мы будем создавать и кэшировать строго типизированный делегат, а не использовать обычное отражение каждый раз, когда вызывается метод Foo.

int x = 42;
MyClass.Foo(x);    // displays "Non-Nullable Struct"

int? y = 123;
MyClass.Foo(y);    // displays "Nullable Struct"

string z = "Test";
MyClass.Foo(z);    // displays "Class"

// ...

public static class MyClass
{
    public static void Foo(T? a) where T : struct
    {
        Console.WriteLine("Nullable Struct");
    }

    public static void Foo(T a)
    {
        Type t = typeof(T);

        Delegate action;
        if (!FooDelegateCache.TryGetValue(t, out action))
        {
            MethodInfo mi = t.IsValueType ? FooWithStructInfo : FooWithClassInfo;
            action = Delegate.CreateDelegate(typeof(Action), mi.MakeGenericMethod(t));
            FooDelegateCache.Add(t, action);
        }
        ((Action)action)(a);
    }

    private static void FooWithStruct(T a) where T : struct
    {
        Console.WriteLine("Non-Nullable Struct");
    }

    private static void FooWithClass(T a) where T : class
    {
        Console.WriteLine("Class");
    }

    private static readonly MethodInfo FooWithStructInfo = typeof(MyClass).GetMethod("FooWithStruct", BindingFlags.NonPublic | BindingFlags.Static);
    private static readonly MethodInfo FooWithClassInfo = typeof(MyClass).GetMethod("FooWithClass", BindingFlags.NonPublic | BindingFlags.Static);
    private static readonly Dictionary FooDelegateCache = new Dictionary();
}

(Обратите внимание, что этот пример не является потоковым .Если вам нужна безопасность потоков, вам придется либо использовать какую-то блокировку во всем доступе к кеш-словарю, либо - если вы можете настроить таргетинг на .NET4 - используйте ConcurrentDictionary .)

508
задан Xavier Poinas 10 February 2011 в 22:12
поделиться