IOCContainer nested dependencies and failed resolves
-
Hello All, I am working on the correct usage of IOCContainer(Autofac) in a project which has mulitple assemblies. I am not able to understand the nested dependency pattern correctly as well as what would be the best exception handling strategy in case of failed resolves. The post is not concise, as I am afraid I cannot explain my confusion in a brief manner. So apologies.. I am trying to use the 'constructor injection pattern' instead of 'property' or 'method' injection. so a class which looked like this:
Class Foo()
{
private static readonly IDependency = IOCContainer.Resolve();
}is changed to something like this
Class Foo(IDependency dependency)
{
private readonly IDependency = dependency;
}however after cleaning up the whole code with the constructor pattern, the code looks like this
Class Foo(){
public Foo(IDependency dependency)
{
this.dependency = dependency;
....
var bar = new Bar(this.dependency);}
}
Class Bar{
public Bar(IDependency dependency) { this.dependency = dependency; }
}
Now if the dependency was not available (IOCContainer failed to resolve this dependency), Foo will pass that dependency around, without worrying about the failed resolved call.. I think that given this scenario, the property or method injection methods seem correct as all the classes are directly calling IOCContainer resolves and then they would have a way to check if the dependency was resolved or not directly from the IOCContainer. However A null check or a try catch can be applied when we access the dependency anyways even with the constructor injection pattern, for e.g.
class Bar()
{
public SomeMethod()
{
(dependency != null ? dependency.doSomething : throw new Exception(DependencyNotAvailable);
}
}Is it correct approach? How should I handle the exceptions from IOCContainer otherwise? Thanks in advance, Preaa
-
Hello All, I am working on the correct usage of IOCContainer(Autofac) in a project which has mulitple assemblies. I am not able to understand the nested dependency pattern correctly as well as what would be the best exception handling strategy in case of failed resolves. The post is not concise, as I am afraid I cannot explain my confusion in a brief manner. So apologies.. I am trying to use the 'constructor injection pattern' instead of 'property' or 'method' injection. so a class which looked like this:
Class Foo()
{
private static readonly IDependency = IOCContainer.Resolve();
}is changed to something like this
Class Foo(IDependency dependency)
{
private readonly IDependency = dependency;
}however after cleaning up the whole code with the constructor pattern, the code looks like this
Class Foo(){
public Foo(IDependency dependency)
{
this.dependency = dependency;
....
var bar = new Bar(this.dependency);}
}
Class Bar{
public Bar(IDependency dependency) { this.dependency = dependency; }
}
Now if the dependency was not available (IOCContainer failed to resolve this dependency), Foo will pass that dependency around, without worrying about the failed resolved call.. I think that given this scenario, the property or method injection methods seem correct as all the classes are directly calling IOCContainer resolves and then they would have a way to check if the dependency was resolved or not directly from the IOCContainer. However A null check or a try catch can be applied when we access the dependency anyways even with the constructor injection pattern, for e.g.
class Bar()
{
public SomeMethod()
{
(dependency != null ? dependency.doSomething : throw new Exception(DependencyNotAvailable);
}
}Is it correct approach? How should I handle the exceptions from IOCContainer otherwise? Thanks in advance, Preaa
I see some things in your code which I would change, and this should hopefully clear things up for you. Basically, you're mixing up IoC with newing stuff. If I were you, I would change the implementations to something like this:
public interface IBar
{
void DoSomethingInteresting();
}public class Bar : IBar
{
private IDependency dependency;
public Bar(IDependency dependency)
{
if (dependency == null) throw new ArgumentNullException("dependency");
this.dependency = dependency;
}public void DoSomethingInteresting() {}
}public class Foo
{
private IDependency dependency;
private IBar bar;
public Foo(IDependency dependency, IBar bar)
{
if (dependency == null) throw new ArgumentNullException("dependency");
if (bar == null) throw new ArgumentNullException("bar");
this.dependency = dependency;
this.bar = bar;
}public void DoSomething()
{
bar.DoSomethingInteresting();
}
}As you can see, we're relying on injecting any dependencies here (i.e. injecting IBar rather than newing up Bar), and we test in the constructor for nulls. That way, we determine early on whether or not an actual implementation has been passed in.
-
I see some things in your code which I would change, and this should hopefully clear things up for you. Basically, you're mixing up IoC with newing stuff. If I were you, I would change the implementations to something like this:
public interface IBar
{
void DoSomethingInteresting();
}public class Bar : IBar
{
private IDependency dependency;
public Bar(IDependency dependency)
{
if (dependency == null) throw new ArgumentNullException("dependency");
this.dependency = dependency;
}public void DoSomethingInteresting() {}
}public class Foo
{
private IDependency dependency;
private IBar bar;
public Foo(IDependency dependency, IBar bar)
{
if (dependency == null) throw new ArgumentNullException("dependency");
if (bar == null) throw new ArgumentNullException("bar");
this.dependency = dependency;
this.bar = bar;
}public void DoSomething()
{
bar.DoSomethingInteresting();
}
}As you can see, we're relying on injecting any dependencies here (i.e. injecting IBar rather than newing up Bar), and we test in the constructor for nulls. That way, we determine early on whether or not an actual implementation has been passed in.
-
Thanks for the answer Pete, This clears my confusion.. Fail early (throw exception in the constructor) is the preferred way. Regards,
It's certainly the way I like to work. That way, I can tell whether or not I've wired my dependencies up properly.