C#中如何判断当前对象是object<T>还是object<T,U>

How can I find out wether the current object is object<T> or object<T,U> in C#

我想知道在 C# 中是否有一种方法可以找出对象是 object<> 还是 object<T,U>

在我的程序中我处理 ConsoleCommands.
这些 classes 继承自 ConsoleCommandBase class.
ConsoleCommand class 是 ConsoleCommandConsoleCommand<>ConsoleCommand<T,U>.

我的目标是在运行时确定我当前正在查看的具体 ConsoleCommand。我不想像我在代码中那样编写大量 if-else 语句来确定当前对象类型。因此我可以在不触及这段代码的情况下添加第三个 ConsoleCommand<T,U,V>

这是我当前的代码。它有效,但我必须告诉它是 typeof(ConsoleCommand<>) 还是 typeof(ConsoleCommand<T,U>).

for (int i = 0; i < commandList.Count; i++)
{
    if (properties[0].Equals(commandList[i].Id))
    {
        if (commandList[i] is ConsoleCommand)
        {
            (commandList[i] as ConsoleCommand).Invoke();
            validCommand = true;
            break;
        }
        else
        {
            validCommand = false;
            var command = commandList[i];
            Type[] types = command.GetMyTypes();
            if(properties.Length - 1 >= types.Length)
            {
                var typeOfCommand = typeof(ConsoleCommand<,>);
                var genericType = typeOfCommand.MakeGenericType(types);
                object[] parameters = new object[types.Length];
                for(int j=0; j<types.Length; j++)
                {
                    parameters[j] = ConvertType(properties[j + 1], types[j]);
                }
                
                genericType.GetMethod("Invoke").Invoke(command, parameters);
                validCommand = true;
            }
            break;
        }
    }
}

你可以这样做。

以下是一些辅助方法。

static bool IsInstanceOf(Type typeToCheck, object instance)
        {
            if(typeToCheck.IsGenericType)
            {
                return IsInstanceOfGenericType(typeToCheck, instance);
            }
            else
            {
                return instance.GetType() == typeToCheck;
            }
        }

        static bool IsInstanceOfGenericType(Type genericType, object instance)
        {
            Type type = instance.GetType();
            while (type != null)
            {
                if (type.IsGenericType &&
                    type.GetGenericTypeDefinition() == genericType)
                {
                    return true;
                }
                type = type.BaseType;
            }
            return false;
        }

用法。

        ConsoleCommandBase v1 = new ConsoleCommand();
        ConsoleCommandBase v2 = new ConsoleCommand<int>();
        ConsoleCommandBase v3 = new ConsoleCommand<int, int>();

        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand), v1));
        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand), v2));
        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand),v3));

        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand<>), v1));
        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand<>), v2));
        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand<>), v3));

        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand<,>), v1));
        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand<,>), v2));
        Console.WriteLine(IsInstanceOf(typeof(ConsoleCommand<,>), v3));

您实际上已经有了所需的代码,只需要将其通用化即可。

对于示例(我对您的代码进行了一些重构,以改进并使其适用于该示例)

    class Foo<X,Z> {
        public string Invoke(X x, Z z) => $"{x} {z}";
    }
    class Bar<A,B,C> {
        public string Invoke(A a, B b, C c) => $"{a} {b} {c}";
    }

    //then to test

    var foo = new Foo<string, int>();
    callCommand(foo, new string[] { "id", "a", "1" });

    var bar = new Bar<string, int, double>();
    callCommand(bar, new string[] { "id", "a", "2", "3.1"});


    void callCommand(object command, string[] properties){
        var typeOfCommand = command.GetType();
        var types = typeOfCommand.GetGenericArguments();
        //var genericType = typeOfCommand.MakeGenericType(types);
        object[] parameters = new object[types.Length];
        for(int j=0; j<types.Length; j++)
        {
            parameters[j] = Convert.ChangeType(properties[j + 1], types[j]);
        }
        
        var x = typeOfCommand.GetMethod("Invoke").Invoke(command, parameters);
        Console.WriteLine(x);
    }

话虽如此,但有更好的方法来解析命令行,尤其是在 .net 核心中。比如System.CommandLine火龙果