I am currently using the .NET Core built in Dependency Injection (DI).
My application is using the Rules Engine Design Pattern.
One of my rules, has a dependency, which has a dependency. So, I have to keep on "newing up" instances of the dependencies. I feel as though there has be a better way.
Here is an example of my code.
This works but I don't like that I have to new up the DataService and the Repository.
var rules = new List<IRule>
{
new Rule1(),
new Rule2(new DataService(new Repository(CnnStr))) //This is what I don't like
};
s.AddTransient<IRulesEngine>(sp => new RulesEngine(rules));
I started setting this up:
s.AddTransient<IRepository>(sp => new Repository(CnnStr));
s.AddTransient<IDataService>(sp => sp.GetRequiredService<DataService>());
Which seem to get me a little closer to what I want. But, I have no idea how to populate the rules list with a list of instances of the rules with out having to have to new up the dependencies (DataService and Repo).
Something like this, but I know this code is not right.
var rules = new List<IRule>
{
s.AddTransient<IRule>(sp => sp.GetRequiredService<Rule1>())
s.AddTransient<IRule>(sp => sp.GetRequiredService<Rule2>())
};
s.AddTransient<IRulesEngine>(sp => new RulesEngine(rules));
Any help would be appreciated.
Thank you.
CodePudding user response:
Register dependencies, required for rules
s.AddTransient<IRepository>(sp => new Repository(CnnStr));
s.AddTransient<IDataService, DataService>(); // you don't need sp here
Then register rules. TryAddEnumerable
ensures that there will be no duplicated implementations of the same interface
s.TryAddEnumerable(new[] {
ServiceDescriptor.Transient<IRule, Rule1>();
ServiceDescriptor.Transient<IRule, Rule2>();
});
Register rules engine
s.AddTransient<IRulesEngine, RulesEngine>();
Note that rules engine should depend on IEnumerable<IRule>
CodePudding user response:
I got this working this morning.
I used a little bit from a lot of the responses. But, the link below suggested by @Daniel A. White is what put it all together for me.
.NET Core dependency injection -> Get all implementations of an interface
And maybe I was over-complicate as @Jeremey Lakeman suggested.
Here is the changes I made in my Program.cs file:
s.AddTransient<IRepository>(sp => new Repository(CnnStr));
s.AddTransient<IDataService, DataService>();
s.AddTransient<IRule, Rule1>();
s.AddTransient<IRule, Rule2>();
s.AddTransient<IRulesEngine, RulesEngine>();
Plus the changes I made to the Rules Engine:
private readonly IEnumerable<IRule> _rules;
public RulesEngine(IEnumerable<IRule> rules)
{
_rules = rules;
}
public void RunRules()
{
foreach (var rule in _rules)
{
rule.Execute(canonical);
}
}