C# 以静态方式通过反射调用非静态方法
我有一个声明虚拟方法的类。但是,此方法的特定实现没有明确地引用“this”对象。它们只返回特定于该类的值 因此,人们可能一直希望不仅在特定对象上调用此方法,而且在类本身上调用此方法。由于这在句法层面上当然是不可能的,我认为至少通过反思是可能的。也就是说,我希望遍历程序集中的所有类,并确定哪个类返回哪个值作为所述方法的响应 但我的天真方法在尝试调用该方法时失败,出现了null引用异常。为什么?我希望它能够成功,因为我使用了一个具体的类来标识具体的重写方法,所以解析该方法不需要“this”对象及其虚拟方法表 我怎样才能让它工作?(当然不包括定义第二个返回相同值的真正静态方法的“解决方案”) 但是,此方法的特定实现没有明确地引用“this”对象 是的,c语言不需要前缀C# 以静态方式通过反射调用非静态方法,c#,reflection,C#,Reflection,我有一个声明虚拟方法的类。但是,此方法的特定实现没有明确地引用“this”对象。它们只返回特定于该类的值 因此,人们可能一直希望不仅在特定对象上调用此方法,而且在类本身上调用此方法。由于这在句法层面上当然是不可能的,我认为至少通过反思是可能的。也就是说,我希望遍历程序集中的所有类,并确定哪个类返回哪个值作为所述方法的响应 但我的天真方法在尝试调用该方法时失败,出现了null引用异常。为什么?我希望它能够成功,因为我使用了一个具体的类来标识具体的重写方法,所以解析该方法不需要“this”对象及其虚
this
,因为它不是必需的
因此,人们可能一直希望不仅在特定对象上调用此方法,而且在类本身上调用此方法
那是不可能做到的。C#不允许实例方法和静态方法具有相同的名称。因此,这个愿望无法解决,另一个解决方案是必要的
由于这在句法层面上当然是不可能的,我认为至少通过反思是可能的
反射只对允许的内容起作用。如果不能同时使用相同名称的静态和实例,反射将无法解决该问题
但我的天真方法在尝试调用该方法时失败,出现了null引用异常。为什么?
因为您调用了null上的实例方法。您的示例可以简化为:
(null as string).Count()
同样的事情,没有反省。不能对null调用Count()
我希望它能够成功,因为我使用了一个具体的类来标识具体的重写方法,所以解析该方法不需要“this”对象及其虚拟方法表
无论如何强制转换空对象,仍然无法对其调用方法
我怎样才能让它工作?(当然不包括定义第二个返回相同值的真正静态方法的“解决方案”)
您不能基于以下要求:
不仅对特定对象调用此方法,还对类本身调用此方法
更新1:
相反,我的要求是在静态上下文中获取实例方法体(值)中包含的明显静态信息,无论解决方案是什么
这确实令人困惑,下面是示例代码:
public class Person
{
// So this is "Static Inforamtion"
public static int StaticInformation()
{
return 1;
}
// instance method
public static int InstanceMethod()
{
return StaticInformation();
}
}
public static class StaticClass
{
public static int StaticContext()
{
return Person.InstanceMethod();
}
}
这是根据你的陈述假设的。这是我能做的最好的描述你的句子代码。对于大多数(如果不是所有的话)的.Net开发人员来说,静态信息应该是一个标记为静态的方法、属性或字段。然而,声明实例体中包含的静态信息是非常模糊的。什么是身体?实例方法的主体还是类的主体
我还想知道为什么会有人想这样做。这似乎只是一个理论问题,无法解决任何现实情况。在C#中,在什么情况下,我会有一个排序()的方法指针,并希望在不知道是否有实例的情况下调用它?如果期望得到相同的结果,那么为什么需要一个实例方法呢?这是可能的,但如果没有对反射系统的一些滥用。我更多地是为了提供信息,因为我认为它说明了C#和.NET如何工作的一些有趣部分。然而,我要提醒的是,这是非常脆弱的,而且肯定是一种非标签的反射 我们需要在这里做两件事。一种是将空接收器传递给实例方法。这可以通过CreateDelegate等机制实现,该机制可以将实例调用转换为静态调用,其中第一个参数是
This
将引用的实例(通常称为接收方)。NET的有趣之处在于,在底层,所有方法都是静态的;实例方法为方法中可用的此
引用保留了第一个参数槽
然而,还有一个问题。您还希望对虚拟方法进行有效的非虚拟调用。C#编译器仅在非常有限的场景中公开这一点,例如通过基引用调用方法时。要直接进行非虚拟调用,唯一的方法是在手动生成的IL中发出调用操作码(而不是CallVirt)
static void Main(string[] args)
{
Type myFirstFooType = typeof(MyFirstFoo);
// locate the underlying methodinfo, properties have get and set methods.
PropertyInfo myFirstStaticValueMethod = myFirstFooType.GetProperty("StaticValue");
MethodInfo getMethod = myFirstStaticValueMethod.GetGetMethod();
// we need to generate a method call that is non-virtual to a virtual method
// this is normally not allowed in C# because it is prone to error and brittle.
// Here we directly emit IL to do so.
var method = new DynamicMethod("NonVirtualGetter", typeof(string), Type.EmptyTypes, typeof(MyFirstFoo), true);
var ilgen = method.GetILGenerator();
ilgen.Emit(OpCodes.Ldnull); // load a null value for the receiver
ilgen.Emit(OpCodes.Call, getMethod); // invoke the getter method
ilgen.Emit(OpCodes.Ret);
// generate a delgate to the dynamic method.
var getter = (Func<string>)method.CreateDelegate(typeof(Func<string>));
string result = getter();
Console.WriteLine("MyFirstFoo.StaticValue == " + result);
}
static void Main(字符串[]args)
{
类型myFirstFooType=typeof(MyFirstFoo);
//找到基础methodinfo,属性有get和set方法。
PropertyInfo myFirstStaticValueMethod=MyFirstFootType.GetProperty(“StaticValue”);
MethodInfo getMethod=myFirstStaticValueMethod.getMethod();
//我们需要生成对虚拟方法的非虚拟方法调用
//这在C#中通常是不允许的,因为它容易出错和脆弱。
//这里我们直接发射IL来实现这一点。
var方法=新的DynamicMethod(“NonVirtualGetter”、typeof(string)、Type.EmptyTypes、typeof(MyFirstFoo)、true);
var ilgen=method.GetILGenerator();
ilgen.Emit(OpCodes.Ldnull);//为接收器加载空值
Emit(OpCodes.Call,getMethod);//调用getter方法
ilgen.Emit(操作码Ret);
//生成动态方法的增量门。
var getter=(Func)method.CreateDelegate(typeof(Func));
字符串结果=getter();
控制台写入线(“M
static void Main(string[] args)
{
Type myFirstFooType = typeof(MyFirstFoo);
// locate the underlying methodinfo, properties have get and set methods.
PropertyInfo myFirstStaticValueMethod = myFirstFooType.GetProperty("StaticValue");
MethodInfo getMethod = myFirstStaticValueMethod.GetGetMethod();
// we need to generate a method call that is non-virtual to a virtual method
// this is normally not allowed in C# because it is prone to error and brittle.
// Here we directly emit IL to do so.
var method = new DynamicMethod("NonVirtualGetter", typeof(string), Type.EmptyTypes, typeof(MyFirstFoo), true);
var ilgen = method.GetILGenerator();
ilgen.Emit(OpCodes.Ldnull); // load a null value for the receiver
ilgen.Emit(OpCodes.Call, getMethod); // invoke the getter method
ilgen.Emit(OpCodes.Ret);
// generate a delgate to the dynamic method.
var getter = (Func<string>)method.CreateDelegate(typeof(Func<string>));
string result = getter();
Console.WriteLine("MyFirstFoo.StaticValue == " + result);
}
public abstract class Foo
{
public string StaticValue
{
get
{
FieldInfo targetField = GetType().GetField("staticValue");
return (string)targetField.GetValue(null);
}
}
}
public class MyFirstFoo: Foo
{
public static string staticValue = "A first attempt to foo-ize Foo.";
}
public class MySecondFoo: Foo
{
public static string staticValue = "A second attempt to foo-ize Foo.";
}