开发者

Dynamically load class for rules engine

开发者 https://www.devze.com 2023-04-11 07:03 出处:网络
I have a XML file that defines a lot of rules. I load the XML file into my rules engine. Depending on what XML file I load i need to pick which namespace I will find the classes I need. Then on each

I have a XML file that defines a lot of rules. I load the XML file into my rules engine.

Depending on what XML file I load i need to pick which namespace I will find the classes I need. Then on each row of the XML I need to determine what class to load.

My XML

<RuleList assembly="BMW">
 <rule>
    <code>2345</code>
    <errorMessage>foo bar</errorMessage>
    <order>1</order>
 </rule>
</RuleList>
<RuleList assembly="FORD">
 <rule>
    <code>0045</code>
    <errorMessage>foo bar</errorMessage>
    <order>3</order>
 </rule>
</RuleList>

I only process one rule list at a time.

Should I be adding an extra XML attribute to each rule defining the ClassName to load? As I do not want 开发者_JAVA技巧to use the code as the classname? Or can I just add the code as an attribute to my class and use that to load it dynamically

For example

namespace FORD 
{
   [code=0045]
   public bool IsValidColor(foo) : IisValid
   {
      return true
   }
}

Can I load classes from the [code=0045] or should I just stored "IsValidColor" in the XML. Is there a performance difference.


Your attribute syntax doesn't work. But something like [Code("0045")] would, if you create CodeAttribute.

There is going to be some performance difference, because you'll have to find the correct type based on the attribute among all types in the assembly. But the difference is most likely going to be negligible.

To actually do it, define the attribute like this:

[AttributeUsage(AttributeTargets.Class)]
class CodeAttribute : Attribute
{
    public CodeAttribute(string code)
    {
        Code = code;
    }

    public string Code { get; private set; }
}

And then find the class like this:

var type =
    (from t in assembly.GetTypes()
     let attr = (CodeAttribute)t
                   .GetCustomAttributes(typeof(CodeAttribute), false)
                   .SingleOrDefault()
     where attr != null && attr.Code == code
     select t)
    .Single();


Either option would have similar performance. If the error codes, error messages, and order will never vary across XML files, you could even have all of the metadata about a rule inside of an attribute instead, and at runtime enumerate through all classes that implement IisValid:

[Rule(Code = "0045", ErrorMessage = "foo bar", Order = 1)]
public class IsValidColor : IisValid
{
    public bool IsValid(Foo bar)
    {
        // validation rules here
    }
}

However, if all of this is customizable, I'd personally go with having the XML file specify the names of the classes to use.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号