Autofac Injection by Caller Type - autofac

Is it possible to inject type to using autofac by the caller type?
I have 2 objects that holds the same member type.
What I want is when Container1 is called Autofac resolve IRegisteredType as RegisteredType with one value as the name parameter on the ctor and different value for Container2 resolve.
class Container1
{
private IRegisteredType _registeredType;
public Container1(IRegisteredType registeredType)
{
_registeredType = registeredType;
}
}
class Container2
{
private IRegisteredType _registeredType;
public Container2(IRegisteredType registeredType)
{
_registeredType = registeredType;
}
}
public interface IRegisteredType{}
public class RegisteredType:IRegisteredType
{
public RegisteredType(string name(){...}
}

Related

C# issue with class instantiation

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

Autofac - One interface, multiple implementations

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();
}
}
}
}

Autofac: Open generics and base interfaces

Given the following interfaces and classes, is there a way in Autofac to
Register a Provider<T> for all classes that have a ProviderAttribute, with T being the type of such a class (Think registering open generics and resolving them with Autofac's MakeGenericType())
Inject these registered providers as, drum roll, IEnumerable<IProviderBase> into the constructor of other classes
Overview:
public class ProviderAttribute : Attribute { }
public interface IProviderBase
{
Type Type { get; }
}
public interface IProvider<T> : IProviderBase
{
DoSomething(T t);
}
public class Provider<T> : IProvider<T>
{
public Type Type
{
get { return typeof (T); }
}
public DoSomething(T t)
{
//...
}
}
I have come up with a crude solution:
var types = GetProviderTypes();
foreach (var type in types)
{
var t = typeof (Provider<>).MakeGenericType(type);
builder.RegisterType(t).As<IProviderBase>();
}

How to use interface in this scenario

I am trying to setup interface method that will give version number:
var versionNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
I am not sure how to implement this in an interface, so that the inheriting class can get the version number?
public interface IVersionProvider
{
string GetVersion();
}
implementation:
internal class /*or struct*/ VersionProvider : IVersionProvider
{
public string GetVersion()
{
System.Reflection.Assembly.GetExecutingAssembly()
.GetName().Version.ToString();
}
}
I made the class internal, because it doesn't need to be externally creatable:
public class Factory
{
IVersionProvider GetVersionProvider() { return new VersionProvider(); }
}
Since the interface is public, external users will be able to call 'GetVersion' on it even though the implementation is private to the assembly.

How to get Castle Windsor to call parameterless constructor?

Currently I have a class that looks like this:
public class MyClass : IMyClass
{
public MyClass()
{
//...
}
public MyClass(IMyRepository repository)
{
//...
}
}
In my config file I have IMyClass registered, but not IMyRepository. My intention is for Windsor to use the constructor that doesn't take any parameters, but I am getting this message:
Can't create component 'MyClass' as it
has dependencies to be satisified.
MyClass is waiting for the following
dependencies:
Services:
- Namespace.IMyRepository which was not registered.
I found another post that says that the container will call the constructor with the most arguments that it can satisfy. So why is it trying to call the constructor with an argument that it doesn't know how to satisfy?
Maybe you're using an old version of Windsor... this works just fine for me:
[TestFixture]
public class WindsorTests {
public interface ISomeInterface {}
public class AService {
public int Id { get; private set; }
public AService() {
Id = 1;
}
public AService(ISomeInterface s) {
Id = 2;
}
}
[Test]
public void Parameters() {
var container = new WindsorContainer();
container.AddComponent<AService>();
var service = container.Resolve<AService>();
Assert.AreEqual(1, service.Id);
}
}