Reputation: 395
I want to implement IoC container using ASP.NET web forms. I'm completed these steps:
Install Ninject
and Ninject.Web
ddl
public class Global : NinjectHttpApplication
Create Kernel
public override IKernel CreateKernel()
{
IKernel kernel = new StandardKernel(new Module.Module());
return kernel;
}
Create Module
public override void Load()
{
Bind<IMetricService>().To<MetricService>();
}
Using Inject on Page
public partial class _Default : Page
{
[Inject]
private IMetricService metricService;
protected void Page_Init(object sender,EventArgs e)
{
metricService = new MetricService(metricService);
}
protected void Page_Load(object sender, EventArgs e)
{
metricService.GetAllMetrics();
}
}
And this is my MetricService
class
public class MetricService : IMetricService
{
[Inject]
private IMetricService _metricService;
public MetricService(IMetricService metricService)
{
this._metricService = metricService;
}
public void GetAllCriteria()
{
_metricService.GetAllCriteria();
Console.WriteLine("metric service");
}
}
As I understand when pass the IMetricService
in MetricService
constructor the IoC container must bind this MetricService
class. I think my mistake is general but I can't understand where.
Upvotes: 2
Views: 203
Reputation: 395
Can I make on this way?
[Inject]
private IMetrics metrics;
protected void Page_Init(object sender, EventArgs e)
{
metrics = new Metrics(metrics);
}
Where I have
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMetrics>().To<Metrics>();
}
This is my Metric class
public class Metrics : IMetrics
{
private IMetrics metrics;
public Metrics(IMetrics metrics)
{
this.metrics = metrics;
}
}
And when I put the metric in Page_Init Ninject Container put the real Metric class or I need to user property to do that.My idea is in the Page and in the Metric class this IMetri* interface to have a valid state.
When I make on this way Exception is thrown
[Inject]
public IMetrics metrics { get; set; }
protected void Page_Init(object sender, EventArgs e)
{
metrics = new Metrics(metrics);
}
Error activating IMetrics using binding from IMetrics to Metrics
A cyclical dependency was detected between the constructors of two services.
Activation path:
3) Injection of dependency IMetrics into parameter metrics of constructor of type Metrics
2) Injection of dependency IMetrics into property metrics of type _Default
1) Request for default_aspx
Suggestions:
1) Ensure that you have not declared a dependency for IMetrics on any implementations of the service.
2) Consider combining the services into a single one to remove the cycle.
3) Use property injection instead of constructor injection, and implement IInitializable
if you need initialization logic to be run after property values have been injected.
Upvotes: 0
Reputation: 32703
You need to use public properties with the Inject
attribute, so they can be seen. Also, don't rely on a concrete implementation of the MetricService
class. The class consuming the service should only rely on an abstracted implementation (the interface, in this case IMetricService
).
public partial class _Default : Page
{
[Inject]
public IMetricService metricService { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
metricService.GetAllMetrics();
}
}
And metric service doesn't need an instance of itself. That's just a recipe for disaster. Change your MetricService class so that it now retrieves all the criteria without the need to call itself via recursion.
public class MetricService : IMetricService
{
public void GetAllCriteria()
{
//this is where you call out to your database
//or do whatever else you need to do to return the criteria
}
}
Also, I take it that GetAllCriteria
is supposed to return something? That's usually what methods that start with the prefix "get" mean. So you'll need to change the return type from void
to the type that you're returning.
Upvotes: 3