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;
}
}
Related
In my application I am using Ninject and the NamedScopeExtension. One of the objects deeper in the object graph needs access to the root object that defined the named scope. It seems to me that DefinesNamedScope() does not also imply InNamedScope() and instead a new root object is created when I request the root.
Example:
using System;
using Ninject;
using Ninject.Extensions.NamedScope;
using Ninject.Syntax;
namespace NInjectNamedScope
{
public interface IScopeRoot
{
Guid Guid { get; }
void DoSomething();
}
public interface IFactory
{
Guid Guid { get; }
IOther CreateOther();
}
public interface IOther
{
void SayHello();
}
internal class ScopeRoot : IScopeRoot
{
private readonly IFactory m_factory;
private readonly IResolutionRoot m_kernel;
public Guid Guid { get; private set; }
public ScopeRoot(IFactory factory, IResolutionRoot kernel)
{
m_factory = factory;
m_kernel = kernel;
Guid = Guid.NewGuid();
}
public void DoSomething()
{
Console.WriteLine("ScopeRoot.DoSomething(): Entering");
Console.WriteLine("ScopeRoot GUID: {0}", Guid);
Console.WriteLine("IFactory GUID: {0}", m_factory.Guid);
var other = m_factory.CreateOther();
Console.WriteLine("ScopeRoot.DoSomething(): Other created");
other.SayHello();
Console.WriteLine("ScopeRoot.DoSomething(): Exiting");
}
}
internal class Factory : IFactory
{
private IResolutionRoot m_kernel;
public Guid Guid { get; private set; }
public Factory(IResolutionRoot kernel)
{
m_kernel = kernel;
Guid = Guid.NewGuid();
}
public IOther CreateOther()
{
return m_kernel.Get<IOther>();
}
}
internal class Other : IOther
{
private readonly IScopeRoot m_root;
private readonly IFactory m_factory;
public Other(IScopeRoot root, IFactory factory)
{
m_root = root;
m_factory = factory;
}
public void SayHello()
{
Console.WriteLine("Other.SayHello(): Hello");
Console.WriteLine("Our IScopeRoot has GUID: {0}", m_root.Guid);
Console.WriteLine("Our IFactory has GUID: {0}", m_factory.Guid);
}
}
public class MainClass
{
public static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<IScopeRoot>().To<ScopeRoot>().DefinesNamedScope("RootScope");
kernel.Bind<IFactory>().To<Factory>().InNamedScope("RootScope");
kernel.Bind<IOther>().To<Other>().InNamedScope("RootScope");
var root = kernel.Get<IScopeRoot>();
root.DoSomething();
Console.ReadKey();
}
}
}
In this example, Other is receiving the same instance of Factory as the root does, but a new instance of ScopeRoot is created instead of injecting the existing instance that defined the named scope.
How can I access the root of the named scope in a factory? Please note that this example is simplified. In reality, there are several layers of objects between the scope root and the factory method, so I cannot simply pass this to the factory.
Yes you're right, out of the box Ninject can't do .DefinesNamedScope().InNamedScope(). Except maybe for late "creation" (factory, lazy) this couldn't work anyway, because it would create a cyclic dependency.
The simplest way to achieve what you want is to create a "root of the root"... well just one class ActualRoot which is bound with DefinesNamedScope() and gets an IRootScope injected, which again will be bound with .InNamedScope(). The bad thing about this is, that you will need to inject/Get<> an ActualRoot instead of a IRootScope.
As far as i remember, what you can also do instead, is:
Bind<IRootScope>().To<RootScope>()
.InNamedScope(scopeName);
and then retrieve it as follows:
IResolutionRoot.Get<IRootScope>(new NamedScopeParameter(scopeName));
This way you don't need a DefinesNamedScope().
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 { }
}
I've this interface:
public interface IRepository<T>
{
List<T> List();
T Get(int Id);
bool Add(T entity);
bool Update(T entity);
}
And I've this class:
public class Customer<T> : IRepository<Entities.Customer>
{
public Entities.Customer Get(int Id)
{
var c = new Entities.Customer();
return c;
}
//continue...
}
How can I cast a generic class to a generic interface like so:
//Other method
public IRepositorio<T> DoStuff<T>(int Id)
{
var a = (IRepository<Entities.Customer>)Activator.CreateInstance(typeof(T)); // ok
var b = (IRepository<T>)Activator.CreateInstance(typeof(T)); // Exception: unable to cast
return object; // an object
}
And I call from this MCV controller:
public ActionResult Home()
{
var repo = new Repository();
repo.DoStuff<Customer<Entities.Custormer>>(10);
return View();
}
My conception is ok? This is possible without dynamic?
Based on the code supplied, I've tried the following which compiles OK
public class Entities {
public class Customer {
}
}
public interface IRepository<T> {
T Get(int Id);
}
public class Customer<T> : IRepository<Entities.Customer> {
public Entities.Customer Get(int Id) {
var cliente = new Entities.Customer();
return cliente;
}
}
public class foo {
public static IRepository<T> DoStuff<T>(int Id) {
var a = (IRepository<Entities.Customer>)Activator.CreateInstance(typeof(T));
var b = (IRepository<T>)Activator.CreateInstance(typeof(T));
return b; // an object
}
}
However, I'm not sure what T is meant to be. When I run and call
foo.DoStuff<Entities.Customer>(0);
then I get a runtime error on the var a line, because the class Entities.Customer does not implement the interface IRepository<T>. If I call
foo.DoStuff<Customer<Entities.Customer>>(0);
then I get the runtime error on the 'var b' line, because the class Customer<Entities.Customer> implements IRepository<Entities.Customer> and not IRepository<Customer<Entities.Customer>>
Both exceptions are correct, so hopefully the author of the question can work out where the problem lies from this answer.
Activator.CreateInstance(typeof(T)); - this creates for you new instance of T, which is Entities.Customer in your example, but it looks like you want to create instance of Customer<Entities.Customer>.
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)).
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