【问题标题】:Reflection: optimize performance反射:优化性能
【发布时间】:2011-04-30 05:30:03
【问题描述】:

我想知道我是否可以优化我的应用程序的反射部分。

背景信息:

vb.net windows 应用程序检查数据库记录是否适用于不同的规则。所以我创建了一个接口iRule 和(到目前为止)54 个正在实现它的规则类。它们都属于同一个项目(Rule.dll)。因为人们应该将它们配置为在特定条件下处于活动状态,所以数据库中还有一个表 tabRule 列出了所有这些规则(使用 RuleKey/RuleName 等)。这似乎是多余的,但我还没有看到替代方案。

言归正传:

我创建为当前记录激活的每个规则的实例。因为记录计数平均为 50000,规则计数为 54,所以创建实例非常耗时。您对如何优化以下部分或针对不同方法的建议有任何想法(共享/静态对象?)?

Dim asmRule As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Rule.dll"))

...后来大约 2700000 次...

' Find the rule in the rules assembly'
Dim ruleObj As Rule.IRule = Nothing, found As Boolean = False
For Each typeAsm As System.Type In asmRule.GetTypes
    If typeAsm.GetInterface(GetType(Rule.IRule).FullName) IsNot Nothing Then
        ruleObj = CType(asmRule.CreateInstance(typeAsm.FullName, True), Rule.IRule)
        If ruleObj.GetKey = ruleRow.RuleKey Then 'ruleRow is the db-counterpart of the rule class'
            found = True
            Exit For
        End If
    End If
Next
'..... execute rule if found....'

谢谢

【问题讨论】:

    标签: .net vb.net reflection interface


    【解决方案1】:

    您能否预先创建每个规则的实例,将它们存储在以 Rule.GetKey 为键的静态字典中,然后当您需要新的时,在字典中找到对象并克隆它?

    在要迭代 50000 行的代码的开头,您可以加载每个规则并将其存储在字典中。现在您只需要迭代行,获取规则键并克隆每行所需的规则。字典查找比通过反射创建对象仅检查其键要快数光年。

    编辑:只是想到了另一种可能的解决方案。您是否有权访问 Rule.dll,因为您正在编译、构建此 dll。在这种情况下,您是否可以添加一个带有单个静态工厂方法的静态帮助器类,该方法将采用 rule.Key 并返回适当的 IRule 对象。那么反射的唯一需要就是加载这个静态类,然后在迭代你的行时,你可以传入规则键并返回适当的规则对象。

    【讨论】:

    • 预先创建规则,确保为每个选项“组合”使用规则的特定实例,这是您可能加快速度的唯一方法
    • 抱歉,那么只需将规则缓存在哈希中并在需要时将它们连接起来。每条规则都需要或多或少是无状态的才能起作用,无论如何它们都应该是无状态的。
    【解决方案2】:

    一个非常小的改进,但不是:

    ruleObj = CType(asmRule.CreateInstance(typeAsm.FullName, True), Rule.IRule)
    

    尝试:

    ruleObj = CType(Activator.CreateInstance(typeAsm, True), Rule.IRule)
    

    您已经有了该类型,因此无需在程序集中再次搜索它。

    【讨论】:

      【解决方案3】:

      也尝试实现这一点:)

      System.Reflection 是“重量级”,我总是先实现更轻的方法..

      //C#

      if (item is IEnumerable) {
          foreach (object o in item as IEnumerable) {
                  //do function
          }
      } else {
          foreach (System.Reflection.PropertyInfo p in obj.GetType().GetProperties())      {
              if (p.CanRead) {
                  Console.WriteLine("{0}: {1}", p.Name, p.GetValue(obj,  null)); //possible function
              }
          }
      }
      

      'VB.Net

        If TypeOf item Is IEnumerable Then
      
          For Each o As Object In TryCast(item, IEnumerable)
                     'Do Function
           Next
        Else
          For Each p As System.Reflection.PropertyInfo In obj.GetType().GetProperties()
               If p.CanRead Then
                     Console.WriteLine("{0}: {1}", p.Name, p.GetValue(obj, Nothing))  'possible function
                End If
            Next
        End If
      

      【讨论】:

      • 感谢您的回答,但实际上我不知道它如何回答我的问题,因为我知道所有规则(接口 iRule 的实现)都在 Rule.dll 中,我只想全部加载一次。但除此之外,@pstrjds 已经回答了。我正在使用我在构造函数中初始化一次的字典。
      猜你喜欢
      • 1970-01-01
      • 2010-09-20
      • 2010-09-30
      • 2013-03-17
      • 2016-05-14
      • 2011-10-17
      • 2014-01-08
      • 1970-01-01
      • 2017-06-02
      相关资源
      最近更新 更多