如何通过反射调用静态抽象方法?[复制]

How to invoke a static abstract method by reflection? [duplicate]

提问人:Zenith 提问时间:9/18/2023 更新时间:9/18/2023 访问量:60

问:

我正在尝试通过反射调用静态抽象方法。在接口上声明静态抽象方法是一项预览功能,您可以在此处阅读更多相关信息。

当调用一个非静态抽象方法时,可以简单地调用该方法并被调用,但是当在继承的接口中声明一个静态抽象方法时,它似乎并没有成为继承类型中的公共静态方法。举个例子:TheType.GetMethod("MethodName").Invoke(null, null)

我有一个声明静态抽象方法的接口:EntityGetTableName()


public interface Entity
{
    public static abstract string GetTableName();
}

然后,有多种类型的 Entities 继承自接口并实现该方法:EntityGetTableName


static string Entity.GetTableName() => "[dbo].[SomeTable]";

当尝试将关键字添加到此实现中时,会给出一条错误消息: ,我将其解释为:接口已将此方法声明为公共方法,因此请删除此关键字。(这是正确的吗?publicThe modifier 'public' is not valid for explicit interface implementation

当尝试调用静态抽象方法并反射实现类型时,找不到该方法并返回 。在调试过程中,我可以看到该方法被声明为该类型的完整限定符,后跟方法名称“GetTableName”,因此我尝试以多种方式调用,例如:GetMethod()nullEntity


var tableName = someType.GetMethod("GetTableName").Invoke(null, null);
var tableName = someType.GetMethod("FullQualifier.Entity.GetTableName").Invoke(null, null);
var tableName = someType.GetMethod("GetTableName", BindingFlags.NonPublic).Invoke(null, null);
var tableName = someType.GetMethod("GetTableName", BindingFlags.Static).Invoke(null, null);

可悲的是,所有返回 null。进一步调试后,该方法似乎被声明为 NonPublic。不过,使用 NonPublic 绑定标志不起作用。如何通过反射调用静态抽象方法?任何帮助将不胜感激。

C# .NET 反射 静态 抽象

评论

1赞 Sweeper 9/18/2023
这回答了你的问题吗?
0赞 Zenith 9/18/2023
确实如此!我不知道怎么做,但根据我的情况调整答案解决了我的问题。不幸的是,我不明白为什么这会起作用。有人可以解释一下吗?
0赞 Zenith 9/18/2023
@Sweeper我觉得这个问题还有一部分没有答案;为什么该方法在声明为公共时是非公开的?
0赞 Sweeper 9/19/2023
它在 IL 级别不是公共的,因为不允许你通过声明的类型直接访问它。您必须通过接口访问显式接口实现。

答:

0赞 Orifjon 9/18/2023 #1

不确定您的代码是如何组织的。以下代码工作正常:

为了获取类型,使用已实现类的类型。 typeof(SomeTableEntity);

using System.Reflection;

namespace ConsoleApp1;

internal class Program
{
    static void Main(string[] args)
    {
        var someType = typeof(SomeTableEntity);
        var tableName = someType.GetMethod("GetTableName").Invoke(null, null);
        Console.WriteLine(tableName);
    }
}


public interface Entity
{
    public static abstract string GetTableName();
}

public class SomeTableEntity : Entity
{
    public static string GetTableName() => "[dbo].[SomeTable]";
}

评论

0赞 Zenith 9/18/2023
也许它有一个区别,那就是?SomeTableEntitysealed record
0赞 Zenith 9/18/2023
区别在于实现方法声明为 Entity.GetTableName()。我不记得为什么,但 VS 要求我这样做。
0赞 Zenith 9/18/2023 #2

正如@Sweeper所建议的那样,看看这篇文章帮助我解决了我的问题;


var getTableNameMethod = (from method
  in SomeType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
  select method
).First()!;
var tableName = getTableNameMethod.Invoke(null, null);

不幸的是,我不知道为什么会这样,所以如果有人理解,请发表评论。