-1

我想重构以下 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 为将来的更多类型运行相同的代码。

4

3 回答 3

2

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

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

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

于 2013-09-25T05:05:01.213 回答
0

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

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

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

于 2013-09-25T05:09:37.347 回答
0

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

首先为方法的每个泛型类型参数调用MethodInfo一种MethodInfo MakeGenericMethod(params Type[] typeArguments)类型。

然后使用您希望在其上调用方法的对象的实例(或者MethodInfo如果它是一个方法)调用结果,以及按顺序包含该方法的参数的对象数组。object Invoke(object obj, object[] parameters)nullstatic

这是修改后的 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
于 2013-09-25T05:29:25.070 回答