如何将类型数组与泛型一起使用

本文关键字:泛型 一起 数组 类型 | 更新日期: 2023-09-27 18:32:37

我想重构以下 C# 代码:

public static T SomeMethod<T>() where T : SomeBaseClass {}
SomeMethod<Foo>().someProperty = sameValue;
SomeMethod<Bar>().someProperty = sameValue;
SomeMethod<Baz>().someProperty = sameValue;
//...

要喜欢这样:

public static T SomeMethod<T>() where T : SomeBaseClass {}
Type[] types = new Type[]{
    typeof(Foo), typeof(Bar), typeof(Baz), //...
};
foreach (Type type in types) {
  // How??
  // SomeMethod<type>().someProperty = sameValue;
}

因此,我想准备类型数组,并在将来使用 foreach 为更多类型运行相同的代码。

如何将类型数组与泛型一起使用

如果你在编译时不知道你的类型是什么,那么使用泛型是没有意义的。
重构代码以将方法签名更改为如下所示的内容:

SomeMethod(Type t){/*do some stuff here*/}

并查看@Florian Gl在评论中提供的链接。

如果你想自动获取从公共基类型继承的所有类型的列表,我会使用反射。 它就像:

var assembly = Assembly.GetAssembly(typeof(SomeBaseClass));
var types = assembly.GetTypes().Where(type => typeof(SomeBaseClass).IsAssignableFrom(type));

也就是说,看起来你正在忙于静态方法,这些方法将在一堆不同的类型上设置静态属性。 你可以为此使用反射,但你最好采取更好的方法来解决这个问题,它不依赖于全局状态(这基本上就是静态属性)。

如果你有 MethodInfo 的泛型方法,你可以通过反射调用它。

首先调用该方法的每个泛型类型参数MethodInfoMethodInfo MakeGenericMethod(params Type[] typeArguments)

然后调用生成的 MethodInfoobject Invoke(object obj, object[] parameters),其中包含要在其上调用方法的对象的实例(如果是 static 方法,则null),以及按顺序包含方法参数的对象数组。

下面是修改后的 c# 代码,用于编译、运行和执行某些操作。 Example1()是你的第一个代码片段。 Example2()执行您希望第二个代码片段执行的操作。

public class SomeBaseClass {
    public string someProperty {
        set {
            Console.WriteLine(string.Format("someProperty called on {0} with {1}", this, value ) );
        }
    }
}
public class Foo : SomeBaseClass {
}
public class Bar : SomeBaseClass {
}
public class Baz : SomeBaseClass {
}
public static class SomeMethods {
    public static T SomeMethod<T>() where T : SomeBaseClass, new() {
        return new T();
    }
}
class Program
{
    public static void Example1() {
        string someValue = "called from Example1";
        SomeMethods.SomeMethod<Foo>().someProperty = someValue;
        SomeMethods.SomeMethod<Bar>().someProperty = someValue;
        SomeMethods.SomeMethod<Baz>().someProperty = someValue;
    }
    public static void Example2() {
        string someValue = "called from Example2";
        Type[] types = new Type[]{
            typeof(Foo), typeof(Bar), typeof(Baz), //...
        };
        foreach (Type type in types) {
            // Here's how:
            System.Reflection.MethodInfo genericMethodInfo = typeof(SomeMethods).GetMethod("SomeMethod");
            System.Reflection.MethodInfo methodInfoForType = genericMethodInfo.MakeGenericMethod(type);
            var someBase = (SomeBaseClass) methodInfoForType.Invoke(null, new object[] { });
            someBase.someProperty = someValue;
        }
    }
    static void Main(string[] args)
    {
        Console.WriteLine("Example1");
        Example1();
        Console.WriteLine("Example2");
        Example2();
        Console.ReadKey();
    }
}

以下是程序的输出:

Example1
someProperty called on ConsoleApplication1.Foo with called from Example1
someProperty called on ConsoleApplication1.Bar with called from Example1
someProperty called on ConsoleApplication1.Baz with called from Example1
Example2
someProperty called on ConsoleApplication1.Foo with called from Example2
someProperty called on ConsoleApplication1.Bar with called from Example2
someProperty called on ConsoleApplication1.Baz with called from Example2