【问题标题】:In Visual Basic .NET, how can I list and call all class functions with a given custom attribute?在 Visual Basic .NET 中,如何列出和调用具有给定自定义属性的所有类函数?
【发布时间】:2017-10-10 12:59:03
【问题描述】:

我有一个基本上充当编辑器的 Windows 窗体/Visual Basic .NET 应用程序。它应该为用户提供的功能之一是能够在他们当前的项目上运行一组规则并报告它发现的任何问题。这些规则都将由表单中的 BackgroundWorker 对象运行,因此可以报告执行进度。

我实现这一点的策略是为表单提供一组私有实例方法,这些方法接收用户的项目数据(例如,包含在 ProjectData 对象中),运行该步骤所需的任何检查,然后返回一个对象,包含有关测试的可显示信息以及它是通过还是失败。 (让我们将此课程称为CheckResult 进行讨论)。所以,为了清楚起见,所有这些方法都有一个签名,如下所示:

Private Function SomeCheckToRun(data As ProjectData) As CheckResult

可以像往常一样定义所有这些方法并手动将它们一一列出以在 BackgroundWorker 的 DoWork 事件处理程序中调用,但这种方法似乎会变得乏味用于潜在的大量检查。如果我可以定义每个我想运行的方法并对其进行修饰,这样循环可以自动找到每个这样的方法定义并运行它,那就太好了。

我想我想做的是定义一个自定义属性类,用于指示哪些实例方法应作为检查运行(可能称为CheckToRunAttribute),然后以某种方式使用反射来获取列表在表单中实现的所有这些方法中,并按顺序执行每个方法,可能通过设置一个委托来为每个方法运行。 BackgroundWorker 可以使用这些方法的总数以及到目前为止已执行的方法来指示总体进度。

到目前为止,我的代码结构在我看来类似于以下内容:

Private Sub MyBackgroundWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles MyBackgroundWorker.DoWork
    ' TODO: Get a list of all the <CheckToRun()> methods here,
    '       run each one in a loop, and report progress after each one.
End Sub

' Further down...

<CheckToRun()>
Private Function SomeCheckToRun(data As ProjectData) As CheckResult
    ' Check code in here.
End Function

<CheckToRun()>
Private Function AnotherCheckToRun(data As ProjectData) As CheckResult
    ' Check code in here.
End Function

<CheckToRun()>
Private Function YetAnotherCheckToRun(data As ProjectData) As CheckResult
    ' Check code in here.
End Function

' And so on...

虽然这不是我有太多经验的事情。我知道 Type.GetMethods() 函数、how to write custom attributesFunc(T, TResult) delegate,但我不知道如何将它们组合在一起以满足我的需求。

tl;dr: 给定一个具有多个私有实例函数的类,它们遵循相同的签名并且都标记有相同的自定义属性,我如何计算有多少然后运行每个?

【问题讨论】:

    标签: vb.net reflection delegates custom-attributes


    【解决方案1】:

    您可以使用反射列出所有具有自定义属性的方法。这是一个 Linq 解决方案:

    Dim methods = Me.GetType.GetMethods(Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)_
                          .Where(Function(m) m.GetCustomAttributes(GetType(CheckToRun), False)_
                          .Length > 0).ToArray()
    

    然后像这样运行它们:

    For Each method As Reflection.MethodInfo In methods
       method.Invoke(Me, New Object() {methodParams})
    Next
    

    【讨论】:

    • 像魅力一样工作!这将为我节省大量工作。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多