I have below classes and implementation inside same class library
public interface IA
{
}
public class A : IA
{
private IB _ib;
public A(IB ib)
{
_ib = ib;
}
}
public interface IB
{
}
public class B : IB
{
private IA _ia;
public B(IA ia)
{
ia = _ia;
}
}
My question is when, either IA or IB, gets instantiated, will it create any circular dependency when performing dependency injection? If so, how can this be resolved?
Your code will have circular dependency and will throw exception at runtime. You need to refactor your code so that A and B do not have dependencies on each other. You will need to extract a new interface (IC) out of either A or B and refactor your code to something like the following:
public interface IA {
}
public class A : IA {
IC _c;
public A(IC c) {
_c = c;
}
}
public interface IB {
}
public class B : IB {
IA _a;
IC _c;
public B(IA a, IC c) {
_a = a;
_c = c;
}
}
public interface IC {
}
public class C : IC {
}
See Circular Dependency in constructors and Dependency Injection on how to refactor your classes to remove circular references
The short answer is that yes, it will be an issue.
There are solutions for it, and these solutions depend on what DI container/solution is being used.
Even if you solve the issue, it a strong signal that your design is not ideal and should be revised.
In most cases you should be able easily extract a third interface which A and B depend on.
Related
I have few classes implementing the same interface, registered under different names. I want to inject them as a collection into a constructor, which unity doesn't understand.
interface IA{}
interface IB { IEnumerable<IA> As { get; set; } }
class A1 : IA{}
class A2 : IA {}
class B : IB
{
public IEnumerable<IA> As { get; set; }
public B(IEnumerable<IA> ass)
{
As = ass;
}
public B(IA a)
{
var b = 1;
}
}
Now I want inject them
[TestMethod]
public void ResolveMultiple()
{
var container = new UnityContainer();
container.RegisterType<IA, A1>("A1");
container.RegisterType<IA, A2>("A2");
container.RegisterType<IB, B>();
var b = container.Resolve<IB>();
Assert.IsNotNull(b);
Assert.IsNotNull(b.As);
var manyAss = container.ResolveAll<IA>();
}
The last line works, so I got collection of two classes (A1, A1) , but B class is not created.
Is there any extra configuration needed?
Ok, the solution is to teach unity to work with IEnumerable
_container.RegisterType(typeof(IEnumerable<>), new InjectionFactory((unityContainer, type, name) => unityContainer.ResolveAll(type.GetGenericArguments().Single())));
I have code similar to this:
class A: IA { ... }
class B: IB {
public B(IA a, ...) { ... }
...
}
class C1 {
public C1(IA a, IB b, ...) { ... }
}
class C2 {
public C2(IA a, IB b, ...) { ... }
}
What I want is only two instances of A -- one to go with C1 and one to go with C2. I want two instances of B. The instance of B passed to C1 should get the same instance of A created for C1. C2 and his parameters should have a different instance of A. How can I configure this scenario in Autofac? It looked like the Owned instance lifetime feature was supposed to handle this, but the posted example was only one layer deep, not two.
My real situation is much more complex. I have a dozen inheritors of IB and a half dozen C defs that take various combinations of the IB inheritors. I wanted to avoid using the named instances because that would bloat my bootstrapper significantly and make it difficult to maintain.
Secondary question: does DryIoc support this? I could be talked into switching.
In DryIoc (which is mine) it may be directly achieved using Reuse.InResolutionScopeOf:
container.Register<C1>(setup: Setup.With(openResolutionScope: true), serviceKey: Some.Blah);
container.Register<C2>(setup: Setup.With(openResolutionScope: true), serviceKey: Some.Blah);
container.Register<IA, A>(reuse: Reuse.InResolutionScopeOf(serviceKey: Some.Blah));
That's it. openResolutionScope: true creates scope in object graph.serviceKey is required to identify/find the scope in graph. For instance if C1 and C2 would implement same interface IC then no need in service key. You just say Reuse.InResolutionScopeOf<IC>() and it will be one IA for each IC object in graph.
You're looking for something called "instance per graph" lifetime scope. It is not supported natively by autofac. If you're not stuck with autofac you can use Castle Windsor as explained in this related/duplicate question.
If you're looking for a solution with autofac itself, you can implement it with InstancePerMatchingLifetimeScope or InstancePerLifetimeScope.
Here's how you configure your container
private IContainer Build()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<A>().As<IA>().InstancePerMatchingLifetimeScope("SomeTag");
builder.RegisterType<B>().As<IB>().InstancePerMatchingLifetimeScope("SomeTag");
builder.RegisterType<C1>();
return builder.Build();
}
Here's how you use it
[Test]
public void PerGraphLifeStyle()
{
var container = Build();
C1 c1;
C1 c2;
using (var scope = container.BeginLifetimeScope("SomeTag"))
{
c1 = scope.Resolve<C1>();
Assert.AreSame(c1.A, c1.B.A);
}
using (var scope = container.BeginLifetimeScope("SomeTag"))
{
c2 = scope.Resolve<C1>();
Assert.AreSame(c1.A, c1.B.A);
}
Assert.AreNotSame(c1.A, c2.A);
}
Dummy classes I created for testing are below
internal interface IA
{
}
class A : IA
{
}
internal interface IB
{
IA A { get; set; }
}
class B : IB
{
public B(IA a)
{
A = a;
}
public IA A { get; set; }
}
class C1
{
public IA A { get; set; }
public IB B { get; set; }
public C1(IA a, IB b)
{
A = a;
B = b;
}
}
I am the customer of a library generating objects of class C which implements two interfaces IA and IB, which represents a permanent connection which I need to store.
I need to store the object C returned between calls.
class Example
{
C _obj;
}
I would like to mock the interface functions used by C for testing, but because 'C' inherits multiple interface I do not have an interface IC, so I cannot write:
class Example
{
Example(IC cInstance) { _obj = cInstance; }
IC _obj;
}
therefore I cannot create easily a mock object that would implement both interfaces IA and IB which I could use for testing that my class Example works.
How do I do this without using casting or something ugly ?
You can do it using generics:
class Example<T> where T : IA, IB
{
public Example(T instance)
{
this.obj = instance;
}
private T obj;
}
You can use C or your mockup with Example as long as that class implements both interfaces:
class CMock : IA, IB
{
// ...
}
var myMockObj = new CMock();
var example = new Example<CMock>(myMockObj);
If the object inherits two interfaces, probably should you store two references:
class Example
{
Example(IA aInstance, IB bInstance) { _a = aInstance; _b = bInstance; }
IA _a;
IB _b;
}
And that's not ugly. On the contrary.
A puzzling architectural question: You have two symmetrical classes A and B. Each A/B object may privately produce a value of type IA/IB using the A.CreateIA()/B.CreateIB() methods. These values are needed by the opposite classes - A needs IB and B needs IA.
The goal is to write the PairMaker.MakePair() function that constructs an interlinks a pair of A and B objects. You also have to write appropriate constructors for the A and B classes. A and B classes are in different assemblies and don't see each other's internals. The link should be secure - the external code should not be able to access or modify the object fields. You can write additional classes and add any methods to A and B as needed - just don't break the security of the link.
interface IA { }
interface IB { }
class A {
IB ib;
//Some constructor
//Other members
IA CreateIA() { }
}
class B {
IA ia;
//Some constructor
//Other members
IB CreateIB() { }
}
class PairMaker {
public static Tuple<A, B> MakePair() {
//What's here?
}
}
This question is similar to How to construct two objects, with each other as a parameter/member, but that question wasn't answered properly.
Here is a possible solution. I don't like how it looks (I hate those out parameters in the constructors).
class A {
IB _ib;
public A(out Func<IA> getter, out Action<IB> setter) {
getter = CreateIA;
setter = SetIB;
}
void SetIB(IB ib) {
_ib = ib;
}
IA CreateIA() { throw new NotImplementedException(); }
}
class B {
IA _ia;
public B(out Func<IB> getter, out Action<IA> setter) {
getter = CreateIB;
setter = SetIA;
}
void SetIA(IA ia) {
_ia = ia;
}
IB CreateIB() { throw new NotImplementedException(); }
}
.
class PairMaker {
public static Tuple<A, B> MakePair() {
Func<IA> iaGetter;
Func<IB> ibGetter;
Action<IA> iaSetter;
Action<IB> ibSetter;
A a = new A(out iaGetter, out ibSetter);
B b = new B(out ibGetter, out iaSetter);
iaSetter(iaGetter());
ibSetter(ibGetter());
return Tuple.Create(a, b);
}
}
public interface IA
{
void DoSomething();
void Calculate();
}
public interface IB
{
void DoSomethingElse();
void Calculate();
}
public class A : IA
{
void DoSomething() { }
void Calculate() {}
}
public class B : IB
{
void DoSomethingElse() { }
void Calculate() {}
}
public class C : IA, IB
{
//How can I implement Calculate() in class B and DoSomething() in class A?
}
How can I avoid duplicate code in class C. Reference: How to simulate multiple inheritance in C#. I don't want to write the full methods again in class C. Thanks for any help.
Assuming that IA.Calculate() is not the same as IB.Calculate() and you therefore can't just make IB inherit from IA, you can implement both interfaces in C by delegating execution on private instances of A and B:
public class C : IA, IB
{
private A _a;
private B _b;
public C()
{
this._a = new A();
this._b = new B();
}
public void DoSomething()
{
this._a.DoSomething();
}
void IA.Calculate()
{
this._a.Calculate();
}
public void DoSomethingElse()
{
this._b.DoSomethingElse();
}
void IB.Calculate()
{
this._b.Calculate();
}
}
Note that you are not achieving multiple inheritance at all. C# has singular inheritance. You are implementing multiple interfaces.
There is absolutely no reason why you cannot implement the interfaces in classes A and B, and then have B derive from A and C derive from B. The method implementations from the interfaces can even be abstract, which forces the child class to do the implementation. If you follow this approach then you can still pass C around as IA or IB simply by casting or using the as keyword.
You can also have interface IB "inherit"1 (implement) IA, which means anything that implements IB must also implement IA.
1 When IB derives from IA it isn't inheritance like it is at the class level, it is actually still implementation. So IB implements IA, it doesn't inherit it.