我有一个通用类:
public class MyList<LinkedItem> : List<LinkedItem> where LinkedItem : MyItem, new()
{
}
从那个泛型类,我想从LinkedItem类访问一个静态函数,它是MyItem类的后代。 (因此无需创建LinkedItem的实例)。
有可能吗?
谢谢,
埃里克
答案 0 :(得分:2)
这不可能直接来自type参数,因为你不能在泛型类型参数上调用静态方法(C#Lang Spec第4.5节)。
不能在成员访问(第7.5.4节)或类型名称(第3.8节)中使用类型参数来标识静态成员或嵌套类型。
是的,这可以通过其他人注意到的反思技巧来实现。但一般来说,使用反射来解决一个简单的方法调用场景就表明设计不好。
更好的设计是传递一个工厂/委托,以一种类型安全的方式封装静态方法。
class MyItem : MyItem {
static void TheFunction() { ... }
}
public class MyList<LinkedItem> : List<LinkedItem> where LinkedItem : MyItem, new()
{
public MyList(Action theStaticFunction) {
...
}
}
new MyList<MyItem>(MyItem.TheFunction);
答案 1 :(得分:2)
可以通过反思来完成。由于 C#对静态成员没有API限制,因此没有直接的方法。
我不确定您的情况是什么,但在大多数情况下,这不是推荐的解决方案:)
public class MyList<LinkedItem> : List<LinkedItem>
where LinkedItem : MyItem, new()
{
public int CallStaticMethod()
{
// Getting a static method named "M" from runtime type of LinkedItem
var methodInfo = typeof(LinkedItem)
.GetMethod("M", BindingFlags.Static | BindingFlags.Public);
// Invoking the static method, if the actual method will expect arguments
// they'll be passed in the array instead of empty array
return (int) methodInfo.Invoke(null, new object[0]);
}
}
public class MyItem
{
}
class MyItemImpl : MyItem
{
public MyItemImpl()
{
}
public static int M()
{
return 100;
}
}
因此,例如下一个代码将打印100
:
public void Test()
{
Console.WriteLine(new MyList<MyItemImpl>().CallStaticMethod());
}
答案 2 :(得分:2)
是的,这是可能的,但您必须通过从typeof(T).GetMethod("Foo", BindingFlags.Public | BindingFlags.Static)
获取MethodInfo然后在其上调用Invoke
来使用反射。
如果在ConstructorInfo而不是MethodInfo上使用相同的技术来创建在构造函数中使用参数的通用工厂,这可能非常有用。虽然很少使用。特别是,在编译时无法保证所讨论的类型具有所需签名的静态方法,因此类型安全性消失,并且在运行时才会捕获此类错误。
答案 3 :(得分:0)
这是不可能的。没有办法在LinkedItem
参数上声明一个约束,该约束表明它必须包含有问题的静态方法。
可能最接近的是:
public class ILinkedItemFactory<T>
{
void YourMethodGoesHere();
}
public class MyList<LinkedItem, Factory> : List<LinkedItem>
where Factory : ILinkedItemFactory<LinkedItem>
where LinkedItem : MyItem, new()
{
public MyList(Factory factory)
{
factory.YourMethodGoesHere();
}
}
答案 4 :(得分:0)
默认情况下,这是不可能的。但是,如果您知道要调用的方法的名称,并且您确信每个LinkedItem
类型都包含此方法,则可以使用反射来实现目标。 注意:对于一般编程任务,通常有一种比解析反射更好的方法。
以下内容始终会为true
输出DoSomething
。它调用一个始终可用的静态成员(我删除了你的泛型类型约束,因为这对于静态方法并不重要)。
public class MyList<LinkedItem> : List<LinkedItem>
{
public bool DoSomething()
{
Type t = typeof(LinkedItem);
object o = new Object();
var result = t.InvokeMember("ReferenceEquals",
BindingFlags.InvokeMethod |
BindingFlags.Public |
BindingFlags.Static,
null,
null, new[] { o, o });
return (result as bool?).Value;
}
}
// call it like this:
MyList<string> ml = new MyList<string>();
bool value = ml.DoSomething(); // true
PS:与此同时,当我输入此内容时,其他人似乎建议使用相同的方法; - )
答案 5 :(得分:0)
这是完全可能的,但不是直接以你所说的方式而不是反思。您可能希望在基类中实现非静态访问方法,并在每个特定的继承类中重写它。
public class MyItem
{
public static void DoSomeStaticStuff() { //DoSomeStaticStuff for MyItem }
public virtual void AccessSomeStaticStuff() { MyItem.DoSomeStaticStuff(); }
}
public class SomeItem : MyItem
{
public static void DoSomeStaticStuff() { //DoSomeStaticStuff for SomeItem }
public override void AccessSomeStaticStuff() { SomeItem.DoSomeStaticStuff(); }
}
然后在你的类中有T:MyItem的约束你只需要调用T.AccessSomeStaticStuff();