Does Simple Injector allow you to pass parameters to constructor when you resolve? I'd like to know if both these frameworks do what Unity's ResolverOverride or DependencyOverride both do.
Simple Injector is thread-safe and its lock-free design allows it to scale linearly with the number of available processors and threads.
can we pass a method as a constructor's parameter ? and why should we do this ? @T. shaped - yes you can and it depends on your scenario! You do not pass method itself but delegate (which is like a pointer to the method).
@AntSwift: Create a factory class, pass IServiceProvider to it, implement a "CreateMyService" method and pass the parameter to it, create/instantiate your class with the required parameter. Inject the factory into your controllers/services instead of the desired service.
I suspect that this question is about passing primitive values to the constructor at the time the service is actually resolved.
Let's set up a simple test class:
public interface IFoo
{
}
public class Foo : IFoo
{
public Foo(string value)
{
}
}
The Foo class takes a string argument that we would like to supply when resolving the IFoo service.
var container = new ServiceContainer();
container.Register<string, IFoo>((factory, value) => new Foo(value));
var firstFoo = container.GetInstance<string, IFoo>("SomeValue");
var secondFoo = container.GetInstance<string, IFoo>("AnotherValue");
If we want to be able to create new instances of the Foo class without using the container directly, we can simply inject a function delegate.
public interface IBar { }
public class Bar : IBar
{
public Bar(Func<string, IFoo> fooFactory)
{
var firstFoo = fooFactory("SomeValue");
var secondFoo = fooFactory("AnotherValue");
}
}
The "composition root" now looks like this:
var container = new ServiceContainer();
container.Register<string, IFoo>((factory, value) => new Foo(value));
container.Register<IBar, Bar>();
var bar = container.GetInstance<IBar>();
If the question is about passing a "static" primitive value to the contructor, this is simply done by registering a factory delegate like this.
var container = new ServiceContainer();
container.Register<IFoo>((factory) => new Foo("SomeValue"));
var firstInstance = container.GetInstance<IFoo>();
var secondInstance = container.GetInstance<IFoo>();
The difference is that this approach does not let you pass a value at resolve time. The value is statically specified at registration time.
Probably the easiest option with Simple Injector is to register with a delegate
[Test]
public void Test1()
{
Container container = new Container();
container.Register<IClassWithParameter>(() => new ClassWithParameter("SomeValue"));
var result = container.GetInstance<IClassWithParameter>();
}
public interface IClassWithParameter { }
public class ClassWithParameter : IClassWithParameter
{
public ClassWithParameter(string parameter)
{
}
}
An advanced option for injecting primitive dependencies is detailed here
The above will all work if your constructor does not have any other dependencies (or you want to resolve these dependencies manually). If you have the scenario below though it falls down:
public class Test : ITest
{
private IFoo _foo;
public Test(string parameter, IFoo foo)
{
_foo = foo;
....
}
}
Now you not only have to manually inject the string but also Foo
. So now your not using dependancy injection at all (really). Also Simple Injector state:
Simple Injector does not allow injecting primitive types (such as integers and string) into constructors.
My reading of this is that they're saying "don't do this".
Another option here is to use "Extensibillity points" for this scenario.
To do this you need to abstract your hard coded elements from your injected elements:
public class Test : ITest
{
private IFoo _foo;
public Test(IFoo foo)
{
_foo = foo;
....
}
public void Init(string parameter)
{
}
}
You can now inject your dependanices and your hardcoded elements:
_container.Register<ITest, Test>();
_container.RegisterInitializer<Test>(instance => {instance.Init("MyValue");});
If you now add another dependancy, your injection will now work without you having to update the config, i.e. your code is nicely de-coupled still:
public class Test : ITest
{
private IFoo _foo;
private IBar _bar;
public Test(IFoo foo, IBar bar)
{
_foo = foo;
_bar = bar;
....
}
public void Init(string parameter)
{
}
}
In response to Liam's answer I would like to point out that there is a simpler way of doing this.
If you have the following situation:
public class Test : ITest
{
private IFoo _foo;
public Test(IFoo foo, string parameter)
{
_foo = foo;
....
}
}
You could write your ioc configuration as below
_container.Register<IFoo, Foo>();
_container.Register<ITest>(
() => new Test(
_container.GetInstance<IFoo>(),
"MyValue"
)
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With