How to inject DbContext into NRules class constructor?

124 views
Skip to first unread message

Alireza Zamani

unread,
Jun 10, 2019, 11:11:06 PM6/10/19
to NRules Users
I am using NRules to define rules and trying to using interface inside NRules base class but something goes wrong and I get "No parameterless constructor defined for this object" error. Here is my Interface definition
{
    public interface ICalcDiscount
    {
        public void ApplyPoint(int point);
    }
    public class CalcDiscount:ICalcDiscount
    {
        private readonly UniContext _context;

       public CalcPoint(UniContext context)
        {
            _context = context;

        }

        public  void ApplyDiscount(int d)
        {
           _context.Discount.Add(new Discount{ CustomerId = 1, d= d});
           _context.SaveChanges();
        }
    }
}

NRule Class

 public class PreferredCustomerDiscountRule : Rule
    {
        private readonly ICalcDiscount _d;

        public PreferredCustomerDiscountRule(ICalcDiscount d)
        {
            _d = d;
        }
        public override void Define()
        {
            Book book = null;


            When()

                .Match(() => book);


            Then()
                .Do(ctx => _c.ApplyDiscount(10));

        }

    }

I have received an error when NRules begin load assembly MissingMethodException: No parameterless constructor defined for this object.

 //Load rules
    var repository = new RuleRepository();
    repository.Load(x => x.From(typeof(PreferredCustomerDiscountRule).Assembly));//problem is here!
 //Compile rules
    var factory = repository.Compile();

Sergiy Nikolayev

unread,
Jun 10, 2019, 11:54:56 PM6/10/19
to NRules Users
I'm assuming you want to use a DI container to construct the rules and inject the dependencies. See https://github.com/NRules/NRules/wiki/Fluent-Rules-Loading#rule-activation how to configure NRules with Autofac DI container. But you can similarly implement a RuleActivator for any other container.

Alireza Zamani

unread,
Jun 11, 2019, 2:32:41 AM6/11/19
to NRules Users
Thank you for your replay, I'm trying to insert something into the database when the condition is true
 When()

                .Match(() => book);


            Then()

                .Do(ctx => _c.ApplyDiscount(10));//Insert into table
*********************************
public  void ApplyDiscount(int d)
        {
           _context.Discount.Add(new Discount{ CustomerId = 1, d= d});
           _context.SaveChanges(); }  
but i have received an error  MissingMethodException: No parameterless constructor defined for this object.

Sergiy Nikolayev

unread,
Jun 11, 2019, 10:40:03 PM6/11/19
to nrules...@googlegroups.com
Someone needs to instantiate your rule, and to do that they need to pass an instance of ICalcDiscount to the constructor.
By default NRules instantiates all rules classes via System.Activator, and that requires those classes to have parameterless constructors - hence the error you are seeing. You can change the default rules activator with your own, where for a given type you return constructed instances. This is usually a job of a DI container, so that is the link I gave you above (with an example using Autofac container).
Alternatively, you can instantiate rule classes yourself, and use RuleDefinitionFactory to convert them to IRuleDefinition instances, which you then compile into ISessionFactory using RuleCompiler.

Sergiy

Alireza Zamani

unread,
Jun 14, 2019, 4:57:43 AM6/14/19
to NRules Users
Thanks, Sergiy.
Reply all
Reply to author
Forward
0 new messages