Reflection: optimize performance
i want to know if i could optimize the reflection part of my app.
Background information:
the vb.net windows application checks if database records apply on different rules. So i created an Interface iRule
and (so far) 54 rules-classes that are implementing it. They all belong to the same project(Rule.dll). Because people should configure them to be active on specific conditions, there's also a table tabRule in Database where all these rules are listed(with RuleKey/RuleName etc.). This seems to be redundant but i haven't seen an alternative.
To come to the point:
I create instances of every Rule that is activated for the current record. Because the record count is avaraged 50000 and the rule-count is 54, the creation of the instances are time consuming. Do you have an idea(shared/static objects?) on how to optimze following part or suggestions for different approaches?
Dim asmRule As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Rule.dll"))
...and later for about 2700000 times ...
' Find the rule in the rules assembly'
Dim ruleObj As Rule.IRule = Nothing, found As Boolean = False
For Each typeAsm A开发者_Python百科s 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....'
Thanks
Could you pre-create instances of each rule, store them in a static dictionary keyed by Rule.GetKey, then when you need a new one, find the object in the dictionary and clone it?
At the beginning of your code that is going to iterate the 50000 rows, you can load each rule and stash it in the dictionary. Now you just have to iterate the rows, get the rule keys and clone the rules you need per row. The dictionary lookup will be light years faster than creating the object via reflection just to check its key.
Edit: Just thought of another possible solution. Do you have access to the Rule.dll, as in are you compiling, building this dll. In that case could you add a static helper class with a single static factory method that would take a rule.Key and return the appropriate IRule object. Then the only need for reflection would be to load this static class, then when iterating your rows you could just pass in the rule key and return back the appropriate rule object.
A really small improvement but instead of:
ruleObj = CType(asmRule.CreateInstance(typeAsm.FullName, True), Rule.IRule)
try:
ruleObj = CType(Activator.CreateInstance(typeAsm, True), Rule.IRule)
You already have the type, so no need to search it once again inside the assembly.
Try to implement this also :)
System.Reflection is "heavy-weight", i always implement a lighter method first..
//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
精彩评论