Single interface: IDoSomething {...}
Two classes implement that interface:
ClassA : IDoSomething {...}
ClassB : IDoSomething {...}
One class uses any of those classes.
public class DummyClass(IDoSomething doSomething) {...}
code without Autofac:
{
....
IDoSomething myProperty;
if (type == "A")
myProperty = new DummyClass (new ClassA());
else
myProperty = new DummyClass (new ClassB());
myProperty.CallSomeMethod();
....
}
Is it possible to implement something like that using Autofac?
Thanks in advance,
What you are looking for is, as I remember, the Strategy Pattern. You may have N implementations of a single interface. As long you register them all, Autofac or any other DI framework should provide them all.
One of the options would be to create a declaration of the property with private setter or only getter inside Interface then implement that property in each of the class. In the class where you need to select the correct implementation, the constructor should have the parameter IEnumerable<ICommon>.
Autofac or any other DI frameworks should inject all possible implementation. After that, you could spin foreach and search for the desired property.
It may look something like this.
public interface ICommon{
string Identifier{get;}
void commonAction();
}
public class A: ICommon{
public string Identifier { get{return "ClassA";} }
public void commonAction()
{
Console.WriteLine("ClassA");
}
}
public class A: ICommon{
public string Identifier { get{return "ClassB";} }
public void commonAction()
{
Console.WriteLine("ClassA");
}
}
public class Action{
private IEnumerable<ICommon> _common;
public Action(IEnumerable<ICommon> common){
_common = common;
}
public void SelectorMethod(){
foreach(var classes in _common){
if(classes.Identifier == "ClassA"){
classes.commonAction();
}
}
}
}
Related
I'm running a C# project on VS2019 with the following code structure:
In the Class1.cs file:
public class Class1
{
public class MyClass2 : Class2
{
...
}
private void RunAlgorithm<T>() where T : Class2, new()
{
T argInstance = new T();
...
}
static void Main(string[] args)
{
RunAlgorithm<MyClass2>();
}
}
In the Class2.cs file:
public class Class2
{
public Class2() { }
public string setParameters { get; set; }
}
I'm getting the following error for the line RunAlgorithm<MyClass2>();
'Class1.MyClass2' must be a non-abstract type with a public
parameterless constructor in order to use it as parameter 'T' in the
generic type or method 'Class1.RunAlgorithm()'
even if I change it to Public, the error persists
Well, minimally, it'll have to be protected so that MyClass can access it..
https://dotnetfiddle.net/XFeEdQ
public class Class1
{
class MyClass2 : Class2
{
}
private void RunAlgorithm<T>() where T : Class2, new()
{
T argInstance = new T();
}
public static void Main(string[] args)
{
new Class1().RunAlgorithm<MyClass2>();
}
}
public class Class2
{
protected Class2() { }
public string setParameters { get; set; }
}
So your "Class1.MyClass2
must have a public parameterless constructor" message is saying that your MyClass needs a constructor. Mine above has such a constructor even though it's not in the code; in the absence of the developer providing a constructor the compiler provides one that does nothing other than call the base parameterless constructor...
...which leads me to the next point; your MyClass2 extends Class2, and hence Class2's constructor needs to be accessible to it. While Class2's constructor is private, MyClass2's constructor can't call it. Every constructor on c# has to either call another constructor or a base constructor. If you don't specify which, the compiler will insert a call to base() for you, which will fail if the base constructor is inaccessible
For this all to work out you need a public parameterless constructor in MyClass2:
public MyClass2():base(){}
or without the base(compiler will add the base call)
or blank (compiler will add all of it)
and you need something that makes Class2's constructor accessible to MyClass2, ie declaring Class2's constructor as public or protected
In my application, I have a service that requires a constructor parameter not resolved by Autofac, that I instantiate using a delegate factory:
public class Service
{
public Service(string parameter /*, ... other dependencies */)
{
}
public delegate Service Factory(string parameter);
}
This works great! I really love this feature.
I also like the Controlled Lifetime relationship, so I can let my component depend on a Func<Owned<ISomething>> like this:
public class Component
{
private Func<Owned<ISomething>> _somethingFactory;
/* constructor omitted for brevity */
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory())
{
/* Lots of useful code here */
}
}
}
My problem is that now I want to combine the two. I can't have an instance of Func<Owned<Service>> injected, because it needs that parameter, so my current solution is to abstract the factory away into another service, say IServiceFactory:
public interface IServiceFactory
{
Service Create(string parameter);
}
...implemented as such:
public class ServiceFactory : IServiceFactory
{
private Service.Factory _internalFactory;
public ServiceFactory(Service.Factory internalFactory)
{
_internalFactory = internalFactory;
}
public Service Create(string parameter)
{
return _internalFactory(parameter);
}
}
My component then becomes this:
public class Component
{
Func<Owned<IServiceFactory>> _serviceFactoryFactory;
/* ... */
}
The need for such a field name leaves a bad taste in my mouth to the point that I suspect there must be a cleaner way to handle this case.
Is there another way?
You could change your injected factory to include the string parameter:
private Func<string, Owned<ISomething>> _somethingFactory;
Then you can pass the string to the factory when you want to create a new instance:
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory("my parameter"))
{
/* Lots of useful code here */
}
}
I've created a .NET Fiddle with a small working sample.
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.
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".
Extensibillity points
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"
)
);
I'd like to implement the Decorator pattern in one of my Mvx projects. That is, I'd like to have two implementations of the same interface: one implementation that is available to all of the calling code, and another implementation that is injected into the first implementation.
public interface IExample
{
void DoStuff();
}
public class DecoratorImplementation : IExample
{
private IExample _innerExample;
public Implementation1(IExample innerExample)
{
_innerExample = innerExample;
}
public void DoStuff()
{
// Do other stuff...
_innerExample.DoStuff();
}
}
public class RegularImplementation : IExample
{
public void DoStuff()
{
// Do some stuff...
}
}
Is it possible to wire up the MvvmCross IoC container to register IExample with a DecoratorImplementation containing a RegularImplementation?
It depends.
If DecoratorImplementation is a Singleton, then you could do something like:
Mvx.RegisterSingleton<IExample>(new DecoratorImplementation(new RegularImplementation()));
Then calls to Mvx.Resolve<IExample>() will return the instance of DecoratorImplementation.
However, if you need a new instance, unfortunately the MvvmCross IoC Container doesn't support that. It would be nice if you could do something like:
Mvx.RegisterType<IExample>(() => new DecoratorImplementation(new RegularImplementation()));
Where you'd pass in a lambda expression to create a new instance, similar to StructureMap's ConstructedBy.
Anyway, you may need to create a Factory class to return an instance.
public interface IExampleFactory
{
IExample CreateExample();
}
public class ExampleFactory : IExampleFactory
{
public IExample CreateExample()
{
return new DecoratorImplementation(new RegularImplementation());
}
}
Mvx.RegisterSingleton<IExampleFactory>(new ExampleFactory());
public class SomeClass
{
private IExample _example;
public SomeClass(IExampleFactory factory)
{
_example = factory.CreateExample();
}
}
I have the following class:
public class MyClass {
#Inject
private MyAnotherClass myAnotherClass;
public MyClass() {
//Perform operations on myAnotherClass.
}
}
I need to do some things in constructor which require an instance of myAnotherClass. Unfortunately myAnotherClass is injected after code in constructor is ran, which means I am performing operations on null...
I could of course instantiate it the classic way (MyAnotherClass myAnotherClass = new MyAnotherClass()) directly in constructor, but I don't think it is the right thing to do in this situation.
What solutions would you suggest to solve this problem?
Best option:
public class MyClass {
private final MyAnotherClass myAnotherClass;
public MyClass(MyAnotherClass other) {
this.myAnotherClass = other;
// And so forth
}
}
T5-IoC will then use constructor injection so there's no need to 'new' up MyClass yourself. See Defining Tapestry IOC Services for more info.
Alternatively:
public class MyClass {
#Inject
private MyAnotherClass myAnotherClass;
#PostInjection
public void setupUsingOther() {
// Called last, after fields are injected
}
}