Depedency injection: injecting partially-initialized objects - dependency-injection

This question is about Unity Container but I guess it is applicable to any dependency container.
I have two classes with circular dependencies:
class FirstClass
{
[Dependency]
public SecondClass Second { get; set; }
}
class SecondClass
{
public readonly FirstClass First;
public SecondClass(FirstClass first)
{
First = first;
}
}
Technically it's possible to instantiate and correctly inject dependencies for both of them if treat them as singletons:
var firstObj = new FirstClass();
var secondObj = new SecondClass(firstObj);
firstObj.Second = secondObj;
When I try to do the same with Unity, I get StackOverflowException:
var container = new UnityContainer();
container.RegisterType<FirstClass>(new ContainerControlledLifetimeManager());
container.RegisterType<SecondClass>(new ContainerControlledLifetimeManager());
var first = container.Resolve<FirstClass>(); // StackOverflowException here!
var second = container.Resolve<SecondClass>(); // StackOverflowException here too!
I understand that Unity tries to protect me from using partially initialized objects but I want to have this protection as an option, not an obligation.
Question: is current behavior disabable?

I think you cannot use circular dependencies with unity at all.
See:
http://msdn.microsoft.com/en-us/library/cc440934.aspx

One way round this would be to use lazy loading for the dependencies on one of the classes:
[TestFixture]
public class CircularUnityTest
{
IUnityContainer container;
[SetUp]
public void SetUp()
{
container = new UnityContainer();
container.RegisterType(typeof(ILazy<>), typeof(Lazy<>));
container.RegisterType<FirstClass>(new ContainerControlledLifetimeManager());
container.RegisterType<SecondClass>(new ContainerControlledLifetimeManager());
}
[Test]
public void CanResolveFirstClass()
{
var first = container.Resolve<FirstClass>();
Assert.IsNotNull(first);
}
[Test]
public void CanResolveSecondClass()
{
var second = container.Resolve<SecondClass>();
Assert.IsNotNull(second);
}
[Test]
public void CanGetFirstFromSecond()
{
var second = container.Resolve<SecondClass>();
Assert.IsNotNull(second.First);
}
}
class FirstClass
{
[Dependency]
public SecondClass Second { get; set; }
}
class SecondClass
{
private readonly ILazy<FirstClass> lazyFirst;
public FirstClass First { get { return lazyFirst.Resolve(); } }
public SecondClass(ILazy<FirstClass> lazyFirst)
{
this.lazyFirst = lazyFirst;
}
}
public interface ILazy<T>
{
T Resolve();
}
public class Lazy<T> : ILazy<T>
{
IUnityContainer container;
public Lazy(IUnityContainer container)
{
this.container = container;
}
public T Resolve()
{
return container.Resolve<T>();
}
}

you can use RegisterInstance instead of RegisterType to achieve your goal. It will behave just like singleton - will use the same instance every time Resolve is invoked. Take a look at this example:
class FirstClass
{
[Dependency]
public SecondClass Second { get; set; }
}
class SecondClass
{
public readonly FirstClass First;
public SecondClass(FirstClass first)
{
First = first;
}
}
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
var firstObj = new FirstClass();
var secondObj = new SecondClass(firstObj);
firstObj.Second = secondObj;
// Register instance instead of type!!!
container.RegisterInstance<FirstClass>(firstObj);
container.RegisterType<SecondClass>();
var first = container.Resolve<FirstClass>();
var second = container.Resolve<SecondClass>();
}
}
Cheers,
Pavel

Related

typemock threw InvalidCast exception

I have following code snipped and I tried to test it using typemock but got InvalidCast exception. ISomeClass is just an interface and SomeClass implements that interface. UseOfSomeClass is another class which uses SomeClass and its constructor takes SomeClass as parameter. I need to test UseOfSomeClass. How do I inject a typemock fake object into a class constructor?
public interface ISomeClass
{
void DoSomething();
}
public class SomeClass : ISomeClass
{
public void DoSomething()
{
Console.WriteLine("Do something!");
}
}
public class UseOfSomeClass
{
public SomeClass SomeClassProperty { get; set; }
public bool IsChecked { get; set; }
public UseOfSomeClass(SomeClass someClass)
{
SomeClassProperty = someClass;
}
public void MyMethod()
{
SomeClassProperty.DoSomething();
IsChecked = true;
}
}
Then test:
[TestClass]
public class UseOfSomeClassTest
{
[TestMethod]
public void TestMethod1()
{
var fakeSomeClass = Isolate.Fake.Instance<ISomeClass>();
var use = new UseOfSomeClass((SomeClass)fakeSomeClass);
use.MyMethod();
Assert.IsTrue(use.IsChecked);
}
}
Thanks!
Typemock Isolator allows you to mock concrete classes, so there's no need to fake ISomeClass in your test case. You can just fake SomeClass and send it as a parameter to the ctor.
[TestMethod, Isolated]
public void TestMethod1()
{
var fakeSomeClass = Isolate.Fake.Instance<SomeClass>();
var use = new UseOfSomeClass(fakeSomeClass);
use.MyMethod();
Assert.IsTrue(use.IsChecked);
}

Autofac. How to get caller class Type?

Suppose we have two classes with same constructor Injectable dependency:
public class FirstClass
{
public FirstClass(ISomeDependency someDependency)
{ }
}
public class SecondClass
{
public SecondClass(ISomeDependency someDependency)
{ }
}
Now we have a registration for ISomeDependency:
builder.Register(x =>
{
string key = GetKeyFromCurrentHttpRequest();
// if "Caller" is "FirstClass" return new Dependency(key);
// else return new Dependency("defaultKey");
}).As<ISomeDependency>();
Note: This is a simplified use case. The real scenario is much more complicated.
1. How to get "Caller" type which tryies to resolve ISomeDependency?
2. Is there a better way design for such situations?
You can use delegate factories do achieve your goal. The only drawback is the FirstClass and SecondClass cannot use ISomeDependency as parameter.
You can try this code in a console application (just add Autofac dependency).
using System;
using Autofac;
namespace test
{
class MainClass
{
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder ();
builder.RegisterType<SomeDependency>().As<ISomeDependency>();
builder.RegisterType<FirstClass>();
builder.RegisterType<SecondClass>();
var container = builder.Build();
var dummy = container.Resolve<FirstClass>();
var dummy2 = container.Resolve<SecondClass>();
}
public interface ISomeDependency
{
}
public class SomeDependency : ISomeDependency
{
public delegate ISomeDependency Factory(string value);
private readonly string _value;
public SomeDependency(string value)
{
_value = value;
Console.WriteLine("Value = " + _value);
}
}
public class FirstClass
{
private ISomeDependency _dependency;
public FirstClass(SomeDependency.Factory factory)
{
_dependency = factory.Invoke("my value");
}
}
public class SecondClass
{
private ISomeDependency _dependency;
public SecondClass(SomeDependency.Factory factory)
{
_dependency = factory.Invoke("my value 2");
}
}
}
}

Autofac, multiple interfaces to same implementation per HTTP request in ASP.NET MVC

My DbContext implementation implements two interfaces.
I'm trying to follow best practices and instantiate one DbContext instance per HTTP request.
However, I have a controller action where I need to instantiate two classes, each of which takes different interface in constructor.
I am worried if in that scenario, for that specific action, two DbContext instances would be raised.
I've setup my ContainerBuilder like this:
builder.RegisterType<MyDbContext>()
.As<IWorkflowPersistenceStore>()
.As<IDocumentPersistenceStore>()
.InstancePerHttpRequest();
builder.RegisterType<WorkflowManager>().As<IWorkflowManager>().InstancePerHttpRequest();
builder.RegisterType<DocumentManager>().As<IDocumentManager>().InstancePerHttpRequest();
public class OperationController : Controller
{
private IWorkflowManager _workflowManager;
private IDocumentManager _documentManager;
public OperationController(IWorkflowManager workflowManager, IDocumentManager documentManager)
{
_workflowManager = workflowManager;
_documentManager = documentManager;
}
public ActionResult SaveWorkflowDocument(...)
{
// will my managers point to same DbContext?
_workflowManager.DoSomething(...);
_documentManager.DoSomethingElse(...);
return View();
}
}
public class WorkflowManager : IWorkflowManager
{
private IWorkflowPersistenceStore _store;
public WorkflowManager(IWorkflowPersistenceStore store)
{
_store = store;
}
}
public class DocumentManager : IDocumentManager
{
private IDocumentPersistenceStore _store;
public DocumentManager (IDocumentPersistenceStore store)
{
_store = store;
}
}
Is this good enough?
Do I have to add .SingleInstance()? I'm worried that it might create singleton for whole application.
I think you're ok with what you have. Test passes:
using Autofac;
using NUnit.Framework;
namespace AutofacTest
{
[TestFixture]
public class ScopeTest
{
[Test]
public void Test()
{
var builder = new ContainerBuilder();
builder.RegisterType<Component>()
.As<IServiceA>()
.As<IServiceB>()
.InstancePerLifetimeScope();
using (var container = builder.Build())
using (var scope = container.BeginLifetimeScope())
{
var a = scope.Resolve<IServiceA>();
var b = scope.Resolve<IServiceB>();
Assert.AreEqual(a, b);
}
}
}
public interface IServiceA { }
public interface IServiceB { }
public class Component : IServiceA, IServiceB { }
}

How to use Ninject to create instances in child classes?

I am learning how to use nInject for a new application I am developing, and I have created the following sample code that can be copied/pasted into a simple console app. It successfully returns an instance of IFoo, but I have a question about it.
How would I modify the code to have the FooManager class create an instance of the Foo object without doing a 'new'. Does the kernal have to be injected as well? But if the kernal is injected and I change the line to read var foo = _kernel.Get<IFoo>(), isn't that introducing a service locator anti-pattern?
namespace IOCTest
{
class Program
{
static void Main(string[] args)
{
using (IKernel kernel = new StandardKernel(new StandardModule()))
{
// do something with the kernal
var mgr = kernel.Get<IFooManager>();
var foo = mgr.GetById(1);
}
}
}
public class StandardModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<IDatabase>()
.To<Database>()
.InTransientScope();
Bind<IFooManager>()
.To<FooManager>()
.InTransientScope();
}
}
//******************************************************
public interface IDatabase
{
object[] GetScalar(int id);
}
public class Database : IDatabase
{
public object[] GetScalar(int id)
{
return new object[] { "RowName" };
}
}
//******************************************************
public interface IFooManager
{
IFoo GetById(int id);
}
public class FooManager : IFooManager
{
private IDatabase _db;
public FooManager(IDatabase db) { _db = db; }
public IFoo GetById(int id)
{
var results = _db.GetScalar(id);
var foo = new Foo(); // <-- HOW DO I ELIMINATE THIS DEPENDENCY?
foo.Name = results[0].ToString();
return foo;
}
}
//******************************************************
public interface IFoo
{
string Name { get; set; }
}
public class Foo : IFoo
{
public string Name { get; set; }
}
//******************************************************
}
First you have to think about the purpose of Foo. Is this some kind of a datacontainer or some service?
In the first case your code is perfect like it is. Datacontainers have no dependencies and shouldn't be created by the IoC container.
In the second case read about Ninject.Extensions.Factory.
http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/
https://github.com/ninject/ninject.extensions.factory/wiki
There are a couple ways to eliminate that dependency. You could do the same thing you did with the Database dependency and use constructor injection. You could do property injection (https://github.com/ninject/ninject/wiki/Injection-Patterns). Another way, and perhaps what you are looking for, would be service location. To do that you can update your FooManager ctor to require an IKernel. This will be resolved automatically and you can then use the kernel that is passed in to get Foo.
public class FooManager : IFooManager
{
private IDatabase _db;
private IKernel _kernel;
public FooManager(IDatabase db, IKernel kernel) { _db = db; _kernel = kernel;}
public IFoo GetById(int id)
{
var results = _db.GetScalar(id);
// var foo = new Foo(); // <-- HOW DO I ELIMINATE THIS DEPENDENCY?
var foo = kernel.Get<IFoo>(); // Like this perhaps
foo.Name = results[0].ToString();
return foo;
}
}

Implementation-less typed factory issues

Take this simple example:
class Program
{
static void Main(string[] args)
{
var windsorContainer = new WindsorContainer();
windsorContainer.Install(new WindsorInstaller());
var editor = windsorContainer.Resolve<IEditor>();
editor.DoSomething();
Console.ReadKey();
}
}
public class WindsorInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ISomeOtherDependency>().ImplementedBy<SomeOtherDependency>());
container.Register(Component.For<IReviewingService>().ImplementedBy<ReviewingService>());
container.Register(Component.For<IEditor>().ImplementedBy<Editor>());
container.Register(Component.For<Func<IReviewingServiceFactory>>().AsFactory());
}
}
public interface IEditor
{
void DoSomething();
}
public class Editor : IEditor
{
private readonly Func<IReviewingServiceFactory> _reviewingService;
public Editor(Func<IReviewingServiceFactory> reviewingService)
{
_reviewingService = reviewingService;
}
public void DoSomething()
{
var rs = _reviewingService();
var reviews = new List<string> {"Review #1", "Review #2"};
var reviewingService = rs.Create(reviews);
reviewingService.Review();
}
}
public interface IReviewingServiceFactory
{
IReviewingService Create(IList<string> reviews);
}
public interface IReviewingService
{
void Review();
}
public class ReviewingService : IReviewingService
{
private readonly IList<string> _reviews;
private readonly ISomeOtherDependency _someOtherDependency;
public ReviewingService(IList<string> reviews, ISomeOtherDependency someOtherDependency)
{
_reviews = reviews;
_someOtherDependency = someOtherDependency;
}
public void Review()
{
Console.WriteLine("Reviewing...");
}
}
public interface ISomeOtherDependency
{
}
public class SomeOtherDependency : ISomeOtherDependency
{
}
With this example I would expect the console to output "Reviewing...". However, Windsor throws exceptions:
No component for supporting the service CastleWindsorTypedFactor.IReviewingServiceFactory was found
What is wrong with my Windsor installer?
You registered Func<IReviewingServiceFactory> instead of IReviewingServiceFactory... try replacing
container.Register(Component.For<Func<IReviewingServiceFactory>>().AsFactory());
with
container.Register(Component.For<IReviewingServiceFactory>().AsFactory());
and adapt the code accordingly - then it should work.
Oh, and another thing - you registered your IReviewingService without specifying a lifestyle, which will default to SINGLETON. That is most likely not what you want, because then your reviews argument will only be passed to the instance when is gets created, which only happens the first time the factory is called...! Additional calls to the factory will return the singleton instance.
Therefore: Change the lifestyle of IReviewingService to transient, AND create an appropriate release method signature on the factory interface (e.g. void Destroy(IReviewingService service)).

Resources