StructureMap - How do I use multiple objects inheriting from the same interface - c#

When using StructureMap I would like class A to be injected with Bar and class B to be injected with Baz.
How would I configure / setup this relationship with StructureMap?
public class Bar : IFoo {}
public class Baz : IFoo {}
public class A
{
private IFoo _foo;
public A(IFoo foo)
{
_foo = foo;
}
}
public class B
{
private IFoo _foo;
public B(IFoo foo)
{
_foo = foo;
}
}

From this answer I think you need to do something like this:
For<IFoo>().Add<Bar>().Named("bar");
For<IFoo>().Add<Baz>().Named("baz");
For<A>()
.Use<A>()
.Ctor<IFoo>()
.Named("bar");
For<B>()
.Use<B>()
.Ctor<IFoo>()
.Named("baz");

Related

Lists of Generics Implementing an interface

I've been reading C# newbie List<Interface> question and can understand why this first example works, but not the second. Why is the first good, but the second piece of code fails to compile.
First the good code:
interface IFoo {}
class Foo : IFoo { }
class Bar : IFoo { }
var list = new List<IFoo>();
list.Add(new Foo());
list.Add(new Bar());
Now for the code which introduces generics
interface IZar<TFoo> where TFoo : IFoo { }
class ZarFoo : IZar<Foo> { }
class ZarBar : IZar<Bar> { }
var list2 = new List<IZar<IFoo>>();
list2.Add(new ZarFoo());
list2.Add(new ZarBar());
This is failing to compile because ZarFoo cannot be converted to IZar when surely it should be able to as it implements IZar where Foo : IFoo?
Because IZar<TFoo> is not co-variant. You can't downcast the interface just like that.
You have to make IZar<TFoo> co-variant, by using out:
interface IZar<out TFoo> where TFoo : IFoo { }
The problem becomes clear when you create an add method:
interface IZar<TFoo> where TFoo : IFoo
{
void Add(TFoo foo);
}
class ZarFoo : IZar<Foo>
{
public void Add(Foo foo)
{ }
}
class ZarBar : IZar<Bar>
{
public void Add(Bar foo)
{ }
}
If you would use the interface, you could end up adding an IFoo, where the actual type is an Foo or Bar. Returning doesn't have that problem since IFoo can be either Foo or Bar. See, there is no inheritance problem:
interface IZar<out TFoo> where TFoo : IFoo
{
TFoo GetOne();
}
class ZarFoo : IZar<Foo>
{
public Foo GetOne()
{ return new Foo(); }
}
class ZarBar : IZar<Bar>
{
public Bar GetOne()
{ return new Bar(); }
}

How to properly use Ninject's NamedScope extension?

I have a pattern that comes up all the time when I'm working. I am almost exclusively a web developer, and Ninject's InRequestScope handles 99% of my needs.
Here's the pattern:
// abstractions
interface IFoo {
void FooMe();
int GetSomeValue();
}
interface IBar {
void BarMe();
}
interface IFooBar {
void FooAndBar();
}
// concrete classes
class Foo : IFoo {
public void FooMe() { Console.WriteLine("I have fooed"); }
public void GetSomeValue() { return 123; }
}
class Bar : IBar {
private readonly IFoo _Foo;
public Bar(IFoo foo) { _Foo = foo; }
public void BarMe() { Console.WriteLine("Bar: {0}", _Foo.GetSomeValue()); }
}
class FooBar : IFooBar {
private readonly IFoo _Foo;
private readonly IBar _Bar;
public Bar(IFoo foo, IBar bar) { _Foo = foo; _Bar = bar; }
public void FooAndBar() {
_Foo.FooMe();
_Bar.BarMe();
}
}
// bindings
kernel.Bind<IFoo>().To<Foo>();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<IFooBar>().To<FooBar>();
What I want to do is set it up such that every time I kernel.Get<IFooBar> it creates exactly one Foo and injects it into the constructors of both Bar and FooBar.
I've experimented with this off and on using the Named Scope extension, but I've never been able to get it to work.
What is the proper binding syntax for this?
so what you've got to do is define some name:
const string FooBarScopeName = "FooBarScope";
and then define the scope:
kernel.Bind<IFooBar>().To<FooBar>()
.DefinesNamedScope(FooBarScopeName);
and bind the Foo in the named scope (the name must match!):
kernel.Bind<IFoo>().To<Foo>();
.InNamedScope(FooBarScope);
Alternative:
There's also InCallScope() which can be used if there's one kernel.Get() for each time a IFooBar is created. In that case, simply do:
kernel.Bind<IFoo>().To<Foo>().InCallScope();

How can I resolve circular dependencies in Funq IoC?

I have two classes which I need to reference each other.
class Foo
{
public Foo(IBar bar) {}
}
class Bar
{
public Bar(IFoo foo) {}
}
When I do:
container.RegisterAutoWiredAs<Foo, IFoo>();
container.RegisterAutoWiredAs<Bar, IBar>();
and when I try to resolve either interface I get a circular dependency graph which results in an infinite loop. Is there an easy way to solve this in Funq or do you know of a workaround?
You can always (and in all containers, I'd say) rely on Lazy as a dependency instead, and that would yield the desired result. In Funq:
public Bar(Lazy<IFoo> foo) ...
public Foo(Lazy<IBar> bar) ...
container.Register<IBar>(c => new Bar(c.LazyResolve<IFoo>());
container.Register<IFoo>(c => new Foo(c.LazyResolve<IBar>());
The answer to your question is no, there is no easy way. Given the code above, it is impossible to construct either class without Funq, so there's no reason to expect Func to be able to do it.
var foo = new Foo(/* what do I pass here? */);
var bar = new Bar(foo);
Of course, if you had another implementation of either IFoo or IBar without the dependency, or you refactored, it might be possible.
In general, the answer to the question "how do I break up circular references when doing Dependency Injection" is: "use property injection".
class Foo
{
public Foo() {}
// Break the dependency cycle by promoting IBar to a property.
public IBar Bar { get; set; }
}
class Bar
{
public Bar(IFoo foo) {}
}
With Funq I think this would be the way to register this dependency.
container.Register<IBar>(c =>
{
var foo = new Foo();
var bar = new Bar(foo);
foo.Bar = bar;
return bar;
});
Furthermore, I agree with Tim Rogers' comment. When you have a circular dependency, there is probably a problem in your design, and you should take a look at it. This is not always wrong, but often is. However, the code you show is very abstract, and there is no way for us to give any feedback on that.
This works for me:
using Funq;
using NUnit.Framework;
namespace FunqIoCyclicReferenceTest
{
[TestFixture]
public class FunqIoCCyclicReferenceTest
{
[Test]
public void Please_Work()
{
var container = new Container();
container.Register<IBar>(c => new Bar());
container.Register<IFoo>(c => new Foo(c.Resolve<IBar>()));
var foo = container.Resolve<IFoo>();
Assert.IsNotNull(foo);
}
}
public class Foo : IFoo
{
public Foo(IBar bar)
{
bar.Foo = this;
Bar = bar;
}
public IBar Bar { get; set; }
}
public interface IBar
{
IFoo Foo { get; set; }
}
public interface IFoo
{
IBar Bar { get; set; }
}
public class Bar : IBar
{
public IFoo Foo { get; set; }
}
}
EDIT
Same idea but without side-effects in constructor:
// interfaces
public interface IBar
{
IFoo Foo { get; set; }
}
public interface IFoo
{
IBar Bar { get; set; }
}
// implementations
public class Foo : IFoo
{
public IBar Bar { get; set; }
}
public class Bar : IBar
{
public IFoo Foo { get; set; }
}
// usage
container.Register<IBar>(c => new Bar());
container.Register<IFoo>(c =>
{
var bar = c.Resolve<IBar>();
var foo = new Foo();
bar.Foo = foo;
foo.Bar = bar;
});
p.s. but I do agree with Tim Rogers - circular reference is a problem to solve.
After registering your types in the container, make the container available as a static variable:
public static class ContainerHolder
{
public static Container Container {get;set;}
}
public class Foo : IFoo
{
private IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
}
public class Bar : IBar
{
private IFoo _foo
{
get { return ContainerHolder.Container.Resolve<IFoo>(); }
}
public Bar()
{
}
}
I had a similar scenario and the dependency between the two classes made me realize they should actually be combined into a single class.

Overloaded constructor passing the same reference multiple times

Lets say I have the following:
public interface IFoo
{
void Foo();
}
public interface IBar
{
void Bar();
}
public class FooAndBar : IFoo, IBar
{
//valid implementation
}
Now I have a class that takes in an IFoo and an IBar in the constructor, but has a paramter-less constructor as well.
public class Consumer
{
private IFoo foo;
private IBar bar;
public Consumer(IFoo foo, IBar bar)
{
this.foo = foo;
this.bar = bar;
}
public Consumer() : this(new FooAndBar(), new FooAndBar()) {}
}
I want to maintain the relationship between the paramter-less constructor calling the parameterized version. But I would like to pass in one referenced object rather than 'new'ing up two FooAndBar instances. Is there anyway to do this while still maintaining the relationship between the constructors?
You can create an interim private constructor that takes a FooAndBar as a parameter:
private Consumer(FooAndBar fooAndBar) : this(fooAndBar, fooAndBar) {}
public Consumer() : this(new FooAndBar()) {}

Two way reference with interfaces and generics

I've got a class with generics which uses another class, which in return needs to know what instance of the initial class "owns" it - which causes problems ;) Let me give an example:
public interface IFoo<T>
{
}
public interface IBar
{
IFoo<IBar> Foo { get; set; }
}
public class Foo<T> : IFoo<T> where T : IBar, new()
{
private readonly T _bar;
public Foo()
{
_bar = new T {Foo = this};
}
}
class Bar : IBar
{
public IFoo<IBar> Foo { get; set; }
}
This doesn't work as Foo = this doesn't work - even if I try to cast this to IFoo (compiles but fails at run time). I've tried to tweak the code various ways, but I've not found an implementation that works...
Hopefully you see what I'm trying to do, and perhaps you even see how I can achieve this ;-)
You can solve this with a combination of an explicit cast in the constructor, along with c#4.0 support for covariance on generic parameters.
First, you need to insert a cast in the Foo<T> constructor:
_bar = new T {Foo = (IFoo<IBar>)this};
Just doing that isn't sufficient, though. Your constraint that T : new() means that T needs to be a concrete class. As such, IFoo<T> will never be exactly IFoo<IBar>. However, if you specify that the generic parameter T for IBar<T> is covariant, then the cast from IFoo<Bar> to IFoo<IBar> will become legal:
public interface IFoo<out T>
The out keyword specifies that the parameter is covariant (which essentially means "this parameter will only be output by methods, never input.")
This MSDN article offers more details on covariance and contravariance.
Would declaring the T type parameter of IFoo as covariant solve your problem?
This code should allow you to do what you are trying:
public interface IFoo<out T> {
}
public interface IBar {
IFoo<IBar> Foo { get; set; }
}
public class Foo<T> : IFoo<T> where T : IBar, new() {
private readonly T _bar;
public Foo() {
_bar = new T { Foo = (IFoo<IBar>)this };
}
}
class Bar : IBar {
public IFoo<IBar> Foo { get; set; }
}
public static class Program {
public static void Main(params string[] args) {
Bar b = new Bar();
Foo<Bar> f = new Foo<Bar>();
}
}

Categories

Resources