簡體   English   中英

如何找出當前對象是否為對象<T>或對象<T,U>在 C# 中

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

我想知道 C# 中是否有辦法找出對象是object<>還是object<T,U>

在我的程序中,我處理ConsoleCommand
這些類繼承自ConsoleCommandBase類。
ConsoleCommand類是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;
        }
    }
}

實際上,您已經擁有所需的代碼,只需將其泛化即可。

例如(我對您的代碼進行了一些重構,以改進並使其適用於示例)

    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 core 中。 例如System.CommandLineDragonFruit

你可以做這樣的事情。

以下是一些輔助方法。

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));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM