First, let's take a look in the code:
using System;
using Autofac;
namespace PropertyInjectionAutofacPoC
{
public interface IInterfaceA { }
public interface IInterfaceB
{
IInterfaceA ClassA { get; set; }
}
public class ClassA : IInterfaceA { }
public class ClassB : IInterfaceB
{
public IInterfaceA ClassA { get; set; } // this is injected properly //
}
public class Z { }
public interface IInterfaceC<T> { }
public interface IInterfaceD<T>
{
IInterfaceA ClassA { get; set; }
IInterfaceC<T> ClassC { get; set; }
}
public interface IInterfaceCZ : IInterfaceC<Z> { }
public abstract class ClassD<T> : IInterfaceD<T>
{
public IInterfaceA ClassA { get; set; } // this is not injected, it's always null //
public IInterfaceC<T> ClassC { get; set; } // this is not injected, it's always null //
}
public abstract class ClassC<T> : IInterfaceC<T> { }
public sealed class ClassCZ : ClassC<Z>, IInterfaceCZ { }
public interface IRepositoryZ : IInterfaceD<Z> { }
public sealed class RepositoryZ : ClassD<Z>, IRepositoryZ { }
internal class Program
{
private static IContainer _container;
private static void Main()
{
try
{
RegisterServices();
// it works //
var a = _container.Resolve<IInterfaceB>();
// it doesn't work //
var b = _container.Resolve<IRepositoryZ>(); // ClassC property is null
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
DisposeServices();
}
}
private static void RegisterServices()
{
var builder = new ContainerBuilder();
builder.RegisterType<ClassA>().As<IInterfaceA>();
builder.RegisterType<ClassB>().As<IInterfaceB>().PropertiesAutowired(); // works like a charm //
builder.RegisterGeneric(typeof(ClassC<>)).As(typeof(IInterfaceC<>)).PropertiesAutowired();
builder.RegisterGeneric(typeof(ClassD<>)).As(typeof(IInterfaceD<>)).PropertiesAutowired(); // it doesn't work //
builder.RegisterType<ClassCZ>().As<IInterfaceCZ>();
builder.RegisterType<RepositoryZ>().As<IRepositoryZ>();
_container = builder.Build();
}
private static void DisposeServices()
{
if (_container != null &&
_container is IDisposable disposable)
disposable.Dispose();
}
}
}
If I change everything to constructors, it works perfectly like a charm but, the main idea for using injected properties here is to avoid the constructor hell.
In the code snippet above, there's some comments where I mentioned what works and what doesn't. The properties injection works properly when there's no generics in use.
So, I'm asking you guys, what am I doing wrong here and what my code is missing to work?
Thanks so much!
The problem you have here is mostly about where you've specified PropertiesAutowired vs what you are resolving.
I've updated your RegisterServices method with some additional comments.
private static void RegisterServices()
{
var builder = new ContainerBuilder();
builder.RegisterType<ClassA>().As<IInterfaceA>();
builder.RegisterType<ClassB>().As<IInterfaceB>().PropertiesAutowired();
// These registrations aren't really valid. You would never be able to
// resolve IInterfaceC<> or IInterfaceD<>, because they are abstract classes, so cannot be constructed.
// You'll always get a NoConstructorsFoundException.
builder.RegisterGeneric(typeof(ClassC<>)).As(typeof(IInterfaceC<>)).PropertiesAutowired();
builder.RegisterGeneric(typeof(ClassD<>)).As(typeof(IInterfaceD<>)).PropertiesAutowired();
builder.RegisterType<ClassCZ>().As<IInterfaceCZ>();
// When I resolve IRepositoryZ, this is the registration that gets provided. So this is where you need PropertiesAutowired.
// Just because RepositoryZ derives from ClassD<Z> does not mean it inherits any of its component registration information,
// which I think is what you may have been expecting.
//
// However, the resolve of IRepositoryZ will now throw a NoConstructorFoundException, because when it goes to inject IInterfaceC<Z>
// onto the property, it hits the invalid registration problem above.
builder.RegisterType<RepositoryZ>().As<IRepositoryZ>().PropertiesAutowired();
_container = builder.Build();
}
Fundamentally, I think you may need to rejig some of your generic class vs concrete class inheritance. I don't think there's a straightforward way to make a generic service be supplied by a concrete registration as you have tried to do here.
Related
Given a set of services that each implement a generic interface where the type parameters all have a common base, how can I write a factory method to return an instance of one of these services? There seems to be no way to write a return type for the factory method.
Here is the sample code, with the problematic method at the bottom:
public abstract class Base
{
public int BaseProp { get; set; }
}
public class Derived1 : Base
{
public int DerivedProp1 { get; set; }
}
public class Derived2 : Base
{
public int DerivedProp2 { get; set; }
}
public interface IHandleStuff<T> where T : Base
{
T GetStuff();
void DoStuff(T t);
}
public class Service1 : IHandleStuff<Derived1>
{
public Derived1 GetStuff() => new();
public void DoStuff(Derived1 t){}
}
public class Service2 : IHandleStuff<Derived2>
{
public Derived2 GetStuff() => new();
public void DoStuff(Derived2 t){}
}
public class Consumer
{
public void DoStuff(Base t)
{
var service = GetServiceFor(t);
service.DoStuff(t);
}
private IHandleStuff<Base> GetServiceFor(Base t)
{
return t.BaseProp switch
{
1 => new Service1(), // Cannot convert expression type 'Service1' to return type 'IHandleStuff<Base>'
2 => new Service2(), // An explicit cast to IHandleStuff<Base> compiles but fails at runtime
_ => throw new ArgumentOutOfRangeException()
};
}
}
Update:
Someone pointed out in a comment (now deleted) that the issue in the above code can be resolved by making the DoStuff and GetServiceFor methods in the Consumer class generic. This works, but at some point in the real code we have to call into this from a non-generic method which knows only the base type. So the suggestion only defers the problem.
i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.
I'm using Unity in with C#. I have an interface I call IConnectionStringLoader, which have two derived interfaces.
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public interface IDbConnectionStringLoader : IConnectionStringLoader
{
}
public interface IMetaDataConnectionStringLoader : IConnectionStringLoader
{
}
It has only one implementation:
public class ConnectionStringLoader : IDbConnectionStringLoader, IMetaDataConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
My registration looks like this:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("DbConnection"));
The point of the interfaces is that I can inject the different interfaces in my classes and get the correct connectionstring for each implementation. But the problem is that whatever registration is done last will overwrite the previous one.
var foo = _container.Resolve<IDbConnectionStringLoader>();
var bar = _container.Resolve<IMetaDataConnectionStringLoader>();
foo.Write();
bar.Write();
Output is:
DbConnection
DbConnection
If I invert the order of the registration the output will be MetaConnection twice. So my conclusion so far is that the last registration overwrites the previous one. However, if I change the implementation to a derived class it works:
public class SomeOtherConnectionStringLoader : ConnectionStringLoader
{
public ConnectionStringLoaderImpl(string connectionStringName) : base(connectionStringName)
{
}
}
And change the registrations:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, SomeOtherConnectionStringLoader >(new InjectionConstructor("DbConnection"));
Now everything works, but I don't understand why. I've tried different lifetimemanagers, but with the same result. I thought Unity would try to create an instance of ConnectionStringLoader with the "correct" injectionparameter based on the interface, but there's seems to be some other logic at play here.
Any suggestions why the registrations overwrite each other?
Honestly speaking, the way you are using the interfaces looks strange to me because there are two interfaces implemented only by the same class. I would find more natural to follow the next approach using registration names:
// If it is a loader the Write method makes no sense (IConnectionStringRepository?)
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
Registrations:
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Database", new InjectionConstructor("MetaConnection"));
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Metadata", new InjectionConstructor("DbConnection"));
Resolutions:
var foo = _container.Resolve<IConnectionStringLoader>("Database");
var bar = _container.Resolve<IConnectionStringLoader>("Metadata");
foo.Write();
bar.Write();
I'm not familiar with Unity. But it seems they are mapping to same instance. So you should change lifetime of ConnectionStringLoader (Per dependency).
If you will not share instance, why do you put all things in one class ? ConnectionStringLoader Methods = IDbConnectionStringLoader methods + IMetaDataConnectionStringLoader methods.
When you resolve IDbConnectionStringLoader it will not use IMetaDataConnectionStringLoader methods which is already in instance (vice versa it's true).
Crating two different derived class is better at this point:
Abstract class:
public abstract class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
Derived Classes:
public sealed class DbConnectionStringLoader : ConnectionStringLoader, IDbConnectionStringLoader
{
public DbConnectionStringLoader(string connectionStringName):base(connectionStringName)
{
}
//Implement methods here just belongs to IDbConnectionStringLoader
}
public sealed class MetaDataConnectionStringLoader : ConnectionStringLoader, IMetaDataConnectionStringLoader
{
public MetaDataConnectionStringLoader(string connectionStringName):base(connectionStringName)
{
}
//Implement methods here just belongs to IMetaDataConnectionStringLoader
}
Surprisingly it does call ConnectionStringLoader ctor twice, but with same injection member. If you look at container.Registrations, there are indeed two registrations so it is not override one with other. I did look at implementation of RegisterType, but didn't get my head around it.
One alternative is to name your registrations, not sure if it fits into your overall unity bootstrap strategy.
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>("bar", new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>("foo", new InjectionConstructor("DbConnection"));
var foo = container.Resolve<IDbConnectionStringLoader>("foo");
var bar = container.Resolve<IMetaDataConnectionStringLoader>("bar");
Hello first of all I'm just a newbie programmer, I just discovered how dependency injection pattern works and it is used to make my code more loosely coupled. I don't specifically know how to configure a Ninject to resolve the dependency, is it better to use these plug in?
Currently my approach when resolving dependency is like this.
public class MyClass
{
IContract _contract = null;
MyClass()
{
}
MyClass(IContract contract)
{
_contract = contract;
}
public void DoSomething()
{
IContract concreteImplementation = _contract ?? new ConcreteContract();
concreteImplementation.MyMethod();
}
}
public class ConcreteContract : IContract
{
public void MyMethod()
{
//do something;
}
}
public interface IContract
{
void MyMethod();
}
Edward...
I thought I'd add a little detail to my comment. The benefits of DI are as you mention (looser coupling). Also, it allows you to register your contract at both compile and runtime, depending on your requirement. As a result, you can add new implementations without breaking the class that you wish to resolve against.
You'll need a slight refactor to accomplish your goal using Unity. Below is a small self contained example (console app), using your class definitions (and showing an alternative implementation):
public class MyClass
{
readonly IContract _contract = null;
// do not include a paramterless ctor
// thus preventing class being created
// without a concrete implementation of IContract
public MyClass(IContract contract)
{
_contract = contract;
}
public void DoSomething()
{
_contract.MyMethod();
}
}
public class ConcreteContract : IContract
{
public ConcreteContract() { }
public void MyMethod()
{
//do something;
Debug.Print("Hello from the ConcreteContract class");
}
}
public class PlasticContract : IContract
{
public PlasticContract() { }
public void MyMethod()
{
//do something;
Debug.Print("Hello from the PlasticContract class");
}
}
public interface IContract
{
void MyMethod();
}
class Program
{
// add the nuget package Unity 1st
// Install-Package Unity
static void Main(string[] args)
{
// Declare a Unity Container -
// normally done once in the Startup/Bootstrap class
var unityContainer = new UnityContainer();
// Register IContract so when dependecy is detected
// it provides a ConcreteContract instance
// you could change this to <IContract, PlasticContract>
unityContainer.RegisterType<IContract, ConcreteContract>();
// Instance a MyClass class object through Unity
var preferredClass = unityContainer.Resolve<MyClass>();
preferredClass.DoSomething();
}
}
Hope this gets you to the next stage.
I'm using the Unity dependency injection framework.
I have two classes, that each take the same delegate parameter in the constructor. Each class should get a different method when resolved.
Can I set this up without using attributes ? If not how would you do it with attributes?
Yep, you can decorate properties or constructor parameters with the [Dependency] attribute.
This example isn't using delegates, it's just using an interface instead, but it shows two of the same interface being registered with different names, and a class requesting a particular one in its constructor:
[TestClass]
public class NamedCI
{
internal interface ITestInterface
{
int GetValue();
}
internal class TestClassOne : ITestInterface
{
public int GetValue()
{
return 1;
}
}
internal class TestClassTwo : ITestInterface
{
public int GetValue()
{
return 2;
}
}
internal class ClassToResolve
{
public int Value { get; private set; }
public ClassToResolve([Dependency("ClassTwo")]ITestInterface testClass)
{
Value = testClass.GetValue();
}
}
[TestMethod]
public void Resolve_NamedCtorDependencyRegisteredLast_InjectsCorrectInstance()
{
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType<ITestInterface, TestClassOne>("ClassOne");
container.RegisterType<ITestInterface, TestClassTwo>("ClassTwo");
container.RegisterType<ClassToResolve>();
var resolvedClass = container.Resolve<ClassToResolve>();
Assert.AreEqual<int>(2, resolvedClass.Value);
}
}
[TestMethod]
public void Resolve_NamedCtorDependencyRegisteredFirst_InjectsCorrectInstance()
{
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType<ITestInterface, TestClassTwo>("ClassTwo");
container.RegisterType<ITestInterface, TestClassOne>("ClassOne");
container.RegisterType<ClassToResolve>();
var resolvedClass = container.Resolve<ClassToResolve>();
Assert.AreEqual<int>(2, resolvedClass.Value);
}
}
}
Instead, you could try passing a factory in on the constructor of the objects. That way you can guarantee (and test) in code exactly what objects are created.