Search code examples
rule-enginebusiness-rulescodeeffects

While rule evaluation Db Connection null exception


I stuck in a scenario while evaluating the rule it initializes the class B and calls the default constructor, but I am injecting the Db Connection through parameter constructor. Please see the below code and advice.

public class A
{
    [ExternalMethod(typeof(B), "IsSpecialWord")]

    [Field(DisplayName = "English Word", Description = "English Word", Max = 200)]
    public string EngWord { get; set; }
}

public class B
{
    public IDbCoonection dbCon { get; set; }
    public B(IDbConnection db)
    {
        dbCon = db;
    }

    [Method("Is Special Word", "Indicates to test abbreviated word")]
    public IsSpecialWord(sting word)
    {
        db.CheckSpecialWord(word);
    }

    public insert SpecialWord(T t)
    {
        db.Insert();
    }

    public update SpecialWord(T t)
    {
        db.Update();
    }
}


public class TestController
{
    A aObj = new A();
    aObj.EngWord ="test";
    IDbConnection db = null;
    if(1)
        db = new SQLDBConnection(connString);
    else
        db = new OracleDBConnection(connectionString);

    B b = new B(db);

    Evaluator<A> evaluator = new Evaluator<A>(editor.Rule.GetRuleXml());
    bool success = evaluator.Evaluate(aObj);
}

Solution

  • If you use an instance external method, the declaring class has to have an empty constructor in order for the engine to be able to instantiate the class and invoke the method successfully.

    In your case, you can declare a Connection property in your source, set its value before the evaluation starts, and pass that source as a parameter in order to use that connection in your external method. Params of the source type are not visible to the rule authors, they are passed automatically to methods by the engine during evaluation. In Rule XML they are declared as <self/> param nodes.

    Here is how this might look like:

    public class A
    {
       public IDbCoonection Connection { get; set; }
    
       // The rest of the source type goes here...
    }
    
    public class B
    {
       public B( ) { } // Empty constructor
    
       [Method("Is Special Word", "Indicates to test abbreviated word")]
       public bool IsSpecialWord( A source, string word )
       {
          source.Connection.CheckSpecialWord(word);
       }
    }
    

    The rule would look like this:

    If Is Special Word ( test ) then Do Something
    

    Note that rule authors don't have to pass the source as param to the method, it happens automatically.