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>
。
在我的程序中我处理 ConsoleCommand
s.
这些 classes 继承自 ConsoleCommandBase
class.
ConsoleCommand
class 是 ConsoleCommand
、ConsoleCommand<>
或 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和火龙果
我想知道在 C# 中是否有一种方法可以找出对象是 object<>
还是 object<T,U>
。
在我的程序中我处理 ConsoleCommand
s.
这些 classes 继承自 ConsoleCommandBase
class.
ConsoleCommand
class 是 ConsoleCommand
、ConsoleCommand<>
或 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和火龙果