Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 以静态方式通过反射调用非静态方法_C#_Reflection - Fatal编程技术网

C# 以静态方式通过反射调用非静态方法

C# 以静态方式通过反射调用非静态方法,c#,reflection,C#,Reflection,我有一个声明虚拟方法的类。但是,此方法的特定实现没有明确地引用“this”对象。它们只返回特定于该类的值 因此,人们可能一直希望不仅在特定对象上调用此方法,而且在类本身上调用此方法。由于这在句法层面上当然是不可能的,我认为至少通过反思是可能的。也就是说,我希望遍历程序集中的所有类,并确定哪个类返回哪个值作为所述方法的响应 但我的天真方法在尝试调用该方法时失败,出现了null引用异常。为什么?我希望它能够成功,因为我使用了一个具体的类来标识具体的重写方法,所以解析该方法不需要“this”对象及其虚

我有一个声明虚拟方法的类。但是,此方法的特定实现没有明确地引用“this”对象。它们只返回特定于该类的值

因此,人们可能一直希望不仅在特定对象上调用此方法,而且在类本身上调用此方法。由于这在句法层面上当然是不可能的,我认为至少通过反思是可能的。也就是说,我希望遍历程序集中的所有类,并确定哪个类返回哪个值作为所述方法的响应

但我的天真方法在尝试调用该方法时失败,出现了null引用异常。为什么?我希望它能够成功,因为我使用了一个具体的类来标识具体的重写方法,所以解析该方法不需要“this”对象及其虚拟方法表

我怎样才能让它工作?(当然不包括定义第二个返回相同值的真正静态方法的“解决方案”)

但是,此方法的特定实现没有明确地引用“this”对象

是的,c语言不需要前缀
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.";
}