jlorenzi (1) [Avatar] Offline
I maintain a rule engine, where we have a bunch of rules for 50 states, and each rule needs to trigger in a specific circumstance, for a specific state, date range, etc. We use custom attributes in .net to define the triggers on a rule, and also use custom attributes to define data elements the rule could reference. So, the rule will end up being one line, calling some helper function that uses the data elements to drive the specifics of what it does.

Here's an example:

[RuleDescription("AZ - Allow OT periodic re-evaluation with OMT codes only once every 14 days")]
[Qualifier("TypeOfBill='WorkersComp' && PT.ReEvalForOT && State='AZ' && ! Modifier='RP' && ServiceDate='10/01/2000'")]
[Data("Limit", 1)]
[Data("Period", 14)]
[Data("DisallowMsg", 260)]

public static ERuleAction AZ_Limit_Periodic_OT_ReEval(BillInfo billInfo, ServiceLine service)
return RuleHelper.AllowPerPeriod(billInfo, service);

The only trick thing here is the Qualifier custom attributes. It takes a free-form string, but then we have a custom interpreter (with a symbol table) that parses it out and determines whether or not to run this rule. It's incredibly flexible and it works insanely well. The RuleHelper function references the data elements to know what the limits to apply are.

The RuleDescription attribute gets pulled out and pushed to the UI, along with the other attributes, but having a rule description helps with logging as well.

Anyway, I didn't really see any mention of metaprogramming with custom attributes like this in your book, so I thought I would post it.