I was wondering if there is a more ellegant pattern for using IOC containers than the way suggested in the codeproject example below.
Surely it is is possible to use an IOC container so that controller constructors are parameterless when you have a solid IOC process in place.
It also means when your application has more than MVC eg WEB-API and whatever else , you are building the same type of solution for that technology.
That doesnt look DRY to me.
Is there a nice pattern someone uses to "register" the Container eg as IMyMagicControllerHat and get singleton using some nice .net System library?
Clearly if you have a UI Depends on Core depends on Model type of application, you are concerned about build dependencies and static calls.
The static calls back to MVCApplication concern me. I was looking for a better approach.
The CODEProject link....
http://www.codeproject.com/Articles/99361/How-To-Use-Unity-Container-In-ASP-NET-MVC-Framewor
In short the relevant code....
public interface IContainerAccessor
{
IUnityContainer Container { get; }
}
public class MvcApplication : HttpApplication, IContainerAccessor
{
private static IUnityContainer _container;
public static IUnityContainer Container
{
get { return _container; }
}
public static IUnityContainer Container
{
get { return _container; }
}
Also there are examples like This from MS that shows a custom static as a solution. http://msdn.microsoft.com/en-us/library/vstudio/hh323691%28v=vs.100%29.aspx I was expecting there might be a well established adapter pattern or similar. Im going to have 100s of accesses to the unity container, so getting the pattern right looks important.
Even blogs that make perfect sense like this, dont show how deep in the application you should get a reference to the original container instance.
http://blog.ploeh.dk/2010/09/29/TheRegisterResolveReleasePattern.aspx
I Appreciate any tips on good ways to solve.
That codeproject article was published in 2010 based on MVC1. MVC3 now contains an IDependencyResolver implementation for better integration with IoC. And for MVC3 with Unity you might look at Unity.MVC3
And if you want to avoid constructor injection you could always register Unity as the default IServiceLocator:
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));
In case anyone is interested, during a google search:
I ended using a custom Global Class. 1 Static Call to start things off.
The rest as Interface/adapter pattern. The example register Unity and Enterprise Library.
And records important details from authenticated request for logging.
... this is a partial extract only... For illustration purposes
Call from MVC Application Global.asax
public class BosMasterWebApplication : System.Web.HttpApplication
{
private bool IsBootStraped;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
IsBootStraped = false;
}
public override void Init()
{
base.Init();
// handlers managed by ASP.Net during Forms authentication
AuthenticateRequest += new EventHandler(AuthHandler);
PostAuthenticateRequest += new EventHandler(PostAuthHandler);
}
public void AuthHandler(object sender, EventArgs e)
{
// if you need to setup anything
}
public void PostAuthHandler(object sender, EventArgs e)
{
// called several times during the authentication process
if (!IsBootStraped)
BosGlobal.HttpBootStrap(this);
if (Request.IsAuthenticated)
{
// did FormsAuthentication.SetAuthCookie was executed if we get here, so set username
BosGlobal.BGA.IBosCurrentState.CurrentUser.SetFromEnvironment();
}
}
}
/// <summary>
/// Central adapter management. Dont abuse this class
/// </summary>
public static class BosGlobal
{
public static IBosGlobalAdpater BGA { get; private set; }
// set up the adapter
static BosGlobal()
{
BGA = new BosGlobalAdapter( );
}
public static void HttpBootStrap(HttpApplication httpApplication)
{
BGA.BootStrap(httpApplication);
}
public static void LocalBootStrap(string machineName)
{ // the LOCAL WPF bootstrap alternative... no http request exists.
BGA.BootStrap(machineName);
}
}
public class BosGlobalAdapter : IBosGlobalAdpater
{
public static bool IsBootStrapped { get; private set; }
/// Unity Container with key dependencies registered
public IUnityContainer IUnityContainer { get; private set; } //IOC Container
//Adapters
public IBosLogAdapter ILogAdapter { get; private set; }
public IBosExceptionManagerAdapter ExceptionManagerAdapter { get; private set; }
public BosGlobalAdapter()
{
IsBootStrapped = false;
IUnityContainer = new UnityContainer();// one container per work process. managing and resolving dependencies
}
public void BootStrap(HttpApplication httpApplication )
{
IBosCurrentState = new BosCurrentState(httpApplication);
BootStrapEnterpriseLibrary();
BootStrapAdapters();
IsBootStrapped = true;
}
private void BootStrapAdapters()
{
ILogAdapter = new BosLogAdapter(IUnityContainer.Resolve<LogWriter>());
ExceptionManagerAdapter = new BosExceptionManagerAdapter(IUnityContainer.Resolve<ExceptionManager>());
}
private void BootStrapEnterpriseLibrary()
{ // now we tell unity about the container manager inside EntLib.
// we dont want 2 containers, so we tell UNity look after EntLib as well please
IUnityContainer.AddNewExtension<EnterpriseLibraryCoreExtension>();
}
Related
i have XMLProductRepository and SQLProductRepository. now how could i switch between them dynamically. i am new in DI. so searching google for the same and found a link which discuss a bit. but still do not understand on what basis the repository will be changed and how. here is the code
public interface IProductRepository
{
IEnumerable<Product> GetAll();
Product Get(int id);
Product Add(Product item);
void Remove(int id);
bool Update(Product item);
}
public class XMLProductRepository : IProductRepository
{
public XMLProductRepository() {}
public IEnumerable<Product> GetAll() {}
public Product Get(int id) {}
public Product Add(Product item) {}
public void Remove(int id) {}
public bool Update(Product item) {}
}
public class SQLProductRepository : IProductRepository
{
public SQLProductRepository() {}
public IEnumerable<Product> GetAll() {}
public Product Get(int id) {}
public Product Add(Product item) {}
public void Remove(int id) {}
public bool Update(Product item) {}
}
Unity.Mvc3 is using as Di
public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
//Register the repository
container.RegisterType<IProductRepository, SQLProductRepository>();
return container;
}
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Bootstrapper.Initialise();
}
public class HomeController : Controller
{
private readonly IProductRepository productRepository;
public HomeController(IProductRepository productRepository)
{
this.productRepository = productRepository;
}
i understand the code that dynamically SQLProductRepository instance is getting injecting into controller. so my question is how to inject XMLProductRepository ?
i want to design something in such a way based on url dependency will be injected.
how to achieve it. looking for guide line. thanks
One possible solution is to inject an IProductRepositoryFactory instead of IProductRepository itself. It would look like this:
interface IProductRepositoryFactory
{
IProductRepository GetRepository(string url);
}
Then your HomeController would look like this:
public class HomeController : Controller
{
private readonly IProductRepositoryFactory productRepositoryFactory;
public HomeController(IProductRepositoryFactory productRepositoryFactory)
{
this.productRepositoryFactory = productRepositoryFactory;
}
}
This way, you'll be able to get required implementation of IProductRepository in your controller action at runtime — all you need is to implement the required logic in the IProductRepositoryFactory.GetRepository(url) method.
Here's a controller action example (note that getting current request URL in such a way makes this method less testable):
public Product Get(string id)
{
return productRepositoryFactory
.GetRepository(Request.Url.ToString())
.GetById(id);
}
UPD: The following is an example implementation of IProductRepositoryFactory. Just implement your own decision-making logic that returns an appropriate instance of IProductRepository based on the URL:
public class ProductRepositoryFactory : IProductRepositoryFactory
{
public IProductRepository GetRepository(string url)
{
if (url.Contains("xml")) { return new XMLProductRepository(); }
if (url.Contains("sql")) { return new SQLProductRepository(); }
throw new ArgumentException("url");
}
}
I don't know where you got the code from, perhaps this question, but the two implementations of IProductRepository that you show have two purposes.
SQLProductRepository will read and write data from and to the database.
XMLProductRepository can read XML and maybe write files.
When running code in a unit test, you generally don't want to connect to a database, but you do sometimes want to use data in a unit test. That's where the XML repository comes in handy. You prepare a data set in XML files that you can commit to version control, you inject another implementation of the requested interface - namely one that reads the XML file - and you don't need a database anymore.
That's why you configure your DI container to inject the SQLProductRepository, while in unit tests you or the DI container will provide an XMLProductRepository when the application requests an IProductRepository.
Now if you say that your controller, your business logic, is to choose SQLProductRepository for one particular request, based on the URI, and XMLProductRepository for the other, then using IProductRepository for that purpose is wrong. That is a problem that should not be solved using your DI container.
Introduce two new interfaces instead and apply those to the repositories:
public interface ISqlProductRepository : IProductRepository
{
}
public interface IXmlProductRepository : IProductRepository
{
}
SQLProductRepository : ISqlProductRepository
XMLProductRepository : IXmlProductRepository
And register and inject those:
// Application startup
container.RegisterType<ISqlProductRepository, SQLProductRepository>();
container.RegisterType<IXmlProductRepository, XMLProductRepository>();
// Controller
private readonly ISqlProductRepository _sqlProductRepository;
private readonly IXmlProductRepository _xmlProductRepository;
public HomeController(ISqlProductRepository sqlProductRepository, IXmlProductRepository xmlProductRepository)
{
_sqlProductRepository = sqlProductRepository;
_xmlProductRepository = xmlProductRepository;
}
public ActionResult SqlMethod1()
{
// use _sqlProductRepository
}
public ActionResult XmlMethod2()
{
// use _xmlProductRepository
}
Of course now you can't inject XMLProductRepository for SQLProductRepository anymore, but that's a problem easily solved using mocking.
Anyway based on your current streak of questions, you're trying to learn something about unit testing and dependency injection. Please pick up a decent book and stop tying pieces together from blog posts, which hardly ever explain everything you need to know.
I'm trying to use SimpleInjector 2.7.3 (IoC container) within an Asp.Net MVC + Web API application.
I've had a couple of problems trying to set it up for both MVC and Web API on the same project until I found this link:
http://methoddev.com/blg/let-s-talk-software/310/simple-injector-in-asp-net-mvc-webapi
After following the link's example, here's what I got:
One of my Web API controllers:
public class UserController : BaseApiController
{
private readonly IUserService service;
public UserController(IUserService userService)
{
// I should point that IUserService is being injected correctly here
this.service = userService;
}
public IHttpActionResult Post(CreateUserRequest request)
{
return Ok();
}
}
The problem happens when I try to execute the Post operation. The CreateUserRequest class itself has a dependency.
public class CreateUserRequest : IValidatableObject
{
private readonly IValidator<CreateUserRequest> validator;
public CreateUserRequest(IValidator<CreateUserRequest> _validator)
{
// _validator is not being injected, I'm getting null here
validator = _validator;
}
public string SomeProperty { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// My validation logic here must call the validator injected
// when the object was created.
return null;
}
}
I should point that IValidator is an interface from the FluentValidator package.
Anyway, when CreateUserRequest is instantiated the validator is null, which means it's not being injected.
When I'm creating the SimpleInjector Container I can see the type correctly registered, so I don't think that is a problem.
I did the following change to CreateUserRequest class:
public class CreateUserRequest : IValidatableObject
{
private readonly CreateUserRequestValidator validator;
// Changed here to the concrete class
public CreateUserRequest(CreateUserRequestValidator _validator)
{
validator = _validator;
}
// ...
}
So, I changed the interface to a concrete class and I'm still receiving a null there.
The only thing I can imagine is that this is somehow related to the custom dependency resolver suggested by the aforementioned link. I needed to use that in order to have the same dependency resolution logic for both MVC and Web API. Here's the code:
public class SimpleInjectorDependencyResolver : System.Web.Mvc.IDependencyResolver,
System.Web.Http.Dependencies.IDependencyResolver,
System.Web.Http.Dependencies.IDependencyScope
{
public SimpleInjectorDependencyResolver(Container container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.Container = container;
}
public Container Container { get; private set; }
public object GetService(Type serviceType)
{
if (!serviceType.IsAbstract && typeof(IController).IsAssignableFrom(serviceType))
{
return this.Container.GetInstance(serviceType);
}
return ((IServiceProvider)this.Container).GetService(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this.Container.GetAllInstances(serviceType);
}
IDependencyScope System.Web.Http.Dependencies.IDependencyResolver.BeginScope()
{
return this;
}
object IDependencyScope.GetService(Type serviceType)
{
return ((IServiceProvider)this.Container).GetService(serviceType);
}
IEnumerable<object> IDependencyScope.GetServices(Type serviceType)
{
return this.Container.GetAllInstances(serviceType);
}
void IDisposable.Dispose()
{
}
}
I don't really know a lot of the plumbing behind MVC and Web API (specially the custom dependency resolver feature), so, I'm really stuck on this one.
I appreciate any help figuring that out. Thanks.
--UPDATE--
In addition to the answer given by Steven, I would like to leave a link to whoever falls into the same problem. It's a great resource:
https://brettedotnet.wordpress.com/2014/07/16/web-api-and-interface-parameters/
The reason why your view model object isn't auto-wired by Simple Injector is because both MVC and Web API don't build view model objects using the IDependencyResolver. So creating a special dependency resolver won't work. If you want to let your view models to be auto-wired, you will have to override the default model binder in MVC and Web API.
But I urge you not to do this. In my opinion, a model binder should just do data conversion and a view model should be a plain DTO. Although it is fine to mark view models with validation attributes, letting them have behavior using services that might even trigger any database communication is a big no-no in my book. This can complicate development tremendously.
This however means that this validator should be injected elsewhere. Without making any changes to your architecture, this basically means you will have to inject that validator in the controller instead:
public class UserController : BaseApiController
{
private readonly IUserService service;
private readonly IValidator<CreateUserRequest> validator;
public UserController(IUserService userService,
IValidator<CreateUserRequest> validator)
{
this.service = userService;
this.validator = validator;
}
}
Obviously this can easily complicate your controllers with extra dependencies and logic, but that's because validation is a cross-cutting concern that you would like to probably keep out of your controllers.
If you try to address this, you will eventually end up with a message passing architecture such as described here.
In a MVC3-application with Ninject.MVC 2.2.0.3 (after merge), instead of injecting repostories directly into controllers I'm trying to make a service-layer that contain the businesslogic and inject the repostories there. I pass the ninject-DependencyResolver to the service-layer as a dynamic object (since I don't want to reference mvc nor ninject there). Then I call GetService on it to get repositories with the bindings and lifetimes I specify in NinjectHttpApplicationModule. EDIT: In short, it failed.
How can the IoC-container be passed to the service-layer in this case? (Different approaches are also very welcome.)
EDIT: Here is an example to illustrate how I understand the answer and comments.
I should avoid the service locator (anti-)pattern and instead use dependency injection. So lets say I want to create an admin-site for Products and Categories in Northwind. I create models, repositories, services, controllers and views according to the table-definitions. The services call directly to the repositories at this point, no logic there. I have pillars of functionality and the views show raw data. These bindings are configured for NinjectMVC3:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICategoryRepository>().To<CategoryRepository>();
kernel.Bind<IProductRepository>().To<ProductRepository>();
}
Repository-instances are created by ninject via two layers of constructor injection, in the ProductController:
private readonly ProductsService _productsService;
public ProductController(ProductsService productsService)
{
// Trimmed for this post: nullchecks with throw ArgumentNullException
_productsService = productsService;
}
and ProductsService:
protected readonly IProductRepository _productRepository;
public ProductsService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
I have no need to decouple the services for now but have prepared for mocking the db.
To show a dropdown of categories in Product/Edit I make a ViewModel that holds the categories in addition to the Product:
public class ProductViewModel
{
public Product Product { get; set; }
public IEnumerable<Category> Categories { get; set; }
}
The ProductsService now needs a CategoriesRepository to create it.
private readonly ICategoryRepository _categoryRepository;
// Changed constructor to take the additional repository
public ProductsServiceEx(IProductRepository productRepository,
ICategoryRepository categoryRepository)
{
_productRepository = productRepository;
_categoryRepository = categoryRepository;
}
public ProductViewModel GetProductViewModel(int id)
{
return new ProductViewModel
{
Product = _productRepository.GetById(id),
Categories = _categoryRepository.GetAll().ToArray(),
};
}
I change the GET Edit-action to return View(_productsService.GetProductViewModel(id)); and the Edit-view to show a dropdown:
#model Northwind.BLL.ProductViewModel
...
#Html.DropDownListFor(pvm => pvm.Product.CategoryId, Model.Categories
.Select(c => new SelectListItem{Text = c.Name, Value = c.Id.ToString(), Selected = c.Id == Model.Product.CategoryId}))
One small problem with this, and the reason I went astray with Service Locator, is that none of the other action-methods in ProductController need the categories-repository. I feel it's a waste and not logical to create it unless needed. Am I missing something?
You don't need to pass the object around you can do something like this
// global.aspx
protected void Application_Start()
{
// Hook our DI stuff when application starts
SetupDependencyInjection();
}
public void SetupDependencyInjection()
{
// Tell ASP.NET MVC 3 to use our Ninject DI Container
DependencyResolver.SetResolver(new NinjectDependencyResolver(CreateKernel()));
}
protected IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new NhibernateModule(),
new ServiceModule(),
new RepoModule()
};
return new StandardKernel(modules);
}
So in this one I setup all the ninject stuff. I make a kernal with 3 files to split up all my binding so it is easy to find.
In my service layer class you just pass in the interfaces you want. This service class is in it's own project folder where I keep all my service layer classes and has no reference to the ninject library.
// service.cs
private readonly IRepo repo;
// constructor
public Service(IRepo repo)
{
this.repo = repo;
}
This is how my ServiceModule looks like(what is created in the global.aspx)
// ServiceModule()
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IRepo>().To<Repo>();
}
}
Seee how I bind the interface to the repo. Now every time it see that interface it will automatically bind the the Repo class to it. So you don't need to pass the object around or anything.
You don't need worry about importing .dll into your service layer. For instance I have my service classes in their own project file and everything you see above(expect the service class of course) is in my webui project(where my views and global.aspx is).
Ninject does not care if the service is in a different project since I guess it is being referenced in the webui project.
Edit
Forgot to give you the NinjectDependecyResolver
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IResolutionRoot resolutionRoot;
public NinjectDependencyResolver(IResolutionRoot kernel)
{
resolutionRoot = kernel;
}
public object GetService(Type serviceType)
{
return resolutionRoot.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return resolutionRoot.GetAll(serviceType);
}
}
I'm in my first time with DDD, so I'm begginer! So, let's take it's very simple :D
I developed an application using asp.net mvc 2 , ddd and nhibernate. I have a domain model in a class library, my repositories in another class library, and an asp.net mvc 2 application. My Repository base class, I have a construct that I inject and dependency (my unique ISessionFactory object started in global.asax), the code is:
public class Repository<T> : IRepository<T>
where T : Entidade
{
protected ISessionFactory SessionFactory { get; private set; }
protected ISession Session
{
get { return SessionFactory.GetCurrentSession(); }
}
protected Repository(ISessionFactory sessionFactory)
{
SessionFactory = sessionFactory;
}
public void Save(T entity)
{
Session.SaveOrUpdate(entity);
}
public void Delete(T entity)
{
Session.Delete(entity);
}
public T Get(long key)
{
return Session.Get<T>(key);
}
public IList<T> FindAll()
{
return Session.CreateCriteria(typeof(T)).SetCacheable(true).List<T>();
}
}
And After I have the spefic repositories, like this:
public class DocumentRepository : Repository<Domain.Document>, IDocumentRepository
{
// constructor
public DocumentRepository (ISessionFactory sessionFactory) : base(sessionFactory)
{ }
public IList<Domain.Document> GetByType(int idType)
{
var result = Session.CreateQuery("from Document d where d.Type.Id = :IdType")
.SetParameter("IdType", idType)
.List<Domain.Document>();
return result;
}
}
there is not control of transaction in this code, and it's working fine, but, I would like to make something to control this repositories in my controller of asp.net mvc, something simple, like this:
using (var tx = /* what can I put here ? */) {
try
{
_repositoryA.Save(objA);
_repositoryB.Save(objB);
_repositotyC.Delete(objC);
/* ... others tasks ... */
tx.Commit();
}
catch
{
tx.RollBack();
}
}
I've heared about NHibernateUnitOfWork, but i don't know :(, How Can I configure NHibernateUnitOfWork to work with my repositories ? Should I change the my simple repository ? Sugestions are welcome!
So, thanks if somebody read to here! If can help me, I appretiate!
PS: Sorry for my english!
bye =D
Session is NHibernate's unit of work. But you can always create your own abstraction of it.
using (var tx = Session.BeginTransaction) { ...
There is an excellent library called NCommon (source) that provides a great UnitOfWork implementation built right in. Version 1.1 allows you to do something like:
public class Foo
{
private readonly IRepository<Stuff> _repository;
public Foo(IRepository<Stuff> repository)
{
_repository = repository;
}
public void DoSomething()
{
using (var scope = new UnitOfWorkScope())
{
_repository.Save(a);
scope.Commit();
}
}
}
It integrates with the latest NHibernate and even uses NHibernate.Linq to provide some powerful querying features. You have little or nothing to build yourself and it works great out of the box.
Edit:
I elaborated on my example to show the full recommended way to use NCommon in a project with dependency-injection.
You can make the Session on your Repository a public property. Then you can do the following:
using(var tx = _repository.Session.BeginTransaction())
On a somewhat related note, this should all be inside of a service layer, not in your controller. Then the controller should have references to your services.
I'm a newbie when it comes to DI and ninject and I'm struggling a bit
about when the actual injection should happen and how to start the
binding.
I'm using it already in my web application and it working fine there,
but now I want to use injection in a class library.
Say I have a class like this:
public class TestClass
{
[Inject]
public IRoleRepository RoleRepository { get; set; }
[Inject]
public ISiteRepository SiteRepository { get; set; }
[Inject]
public IUserRepository UserRepository { get; set; }
private readonly string _fileName;
public TestClass(string fileName)
{
_fileName = fileName;
}
public void ImportData()
{
var user = UserRepository.GetByUserName("myname");
var role = RoleRepository.GetByRoleName("myname");
var site = SiteRepository.GetByID(15);
// Use file etc
}
}
I want to use property injection here because I need to pass in a
filename in my constructor. Am I correct in saying that if I need to
pass in a constructor parameter, I cannot use constructor injection?
If I can use constructor injection with additional parameters, how do
I pass those parameters in?
I have a console app that consumes by Test class that looks as
follows:
class Program
{
static void Main(string[] args)
{
// NinjectRepositoryModule Binds my IRoleRepository etc to concrete
// types and works fine as I'm using it in my web app without any
// problems
IKernel kernel = new StandardKernel(new NinjectRepositoryModule());
var test = new TestClass("filename");
test.ImportData();
}
}
My problem is that when I call test.ImportData() my repositories are null - nothing has been injected into them. I have tried creating another module and calling
Bind<TestClass>().ToSelf();
as I thought this might resolve all injection properties in TestClass but I'm getting nowhere.
I'm sure this is a trivial problem, but I just can't seem to find out
how to go about this.
You are directly newing TestClass, which Ninject has no way of intercepting - remember there's no magic like code transformation intercepting your news etc.
You should be doing kernel.Get<TestClass> instead.
Failing that, you can inject it after you new it with a kernel.Inject( test);
I think there's an article in the wiki that talks about Inject vs Get etc.
Note that in general, direct Get or Inject calls are a Doing It Wrong smell of Service Location, which is an antipattern. In the case of your web app, the NinjectHttpModule and PageBase are the hook that intercepts object creation - there are similar interceptors / logical places to intercept in other styles of app.
Re your Bind<TestClass>().ToSelf(), generally a StandardKernel has ImplicitSelfBinding = true which would make that unnecessary (unless you want to influence its Scope to be something other than .InTransientScope()).
A final style point:- you're using property injection. There are rarely good reasons for this, so you should be using constructor injection instead.
And do go buy Dependency Injection in .NET by #Mark Seemann, who has stacks of excellent posts around here which cover lots of important but subtle considerations in and around the Dependency Injection area.
OK,
I've found out how to do what I need, thanks in part to your comments Ruben. I've created a new module that basically holds the configuration that I use in the class library. Within this module I can either Bind using a placeholder Interface or I can add a constructor parameter to the CustomerLoader.
Below is the code from a dummy console app to demonstrating both ways.
This might help someone else getting started with Ninject!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject.Core;
using Ninject.Core.Behavior;
namespace NinjectTest
{
public class Program
{
public static void Main(string[] args)
{
var kernel = new StandardKernel(new RepositoryModule(), new ProgramModule());
var loader = kernel.Get<CustomerLoader>();
loader.LoadCustomer();
Console.ReadKey();
}
}
public class ProgramModule : StandardModule
{
public override void Load()
{
// To get ninject to add the constructor parameter uncomment the line below
//Bind<CustomerLoader>().ToSelf().WithArgument("fileName", "string argument file name");
Bind<LiveFileName>().To<LiveFileName>();
}
}
public class RepositoryModule : StandardModule
{
public override void Load()
{
Bind<ICustomerRepository>().To<CustomerRepository>().Using<SingletonBehavior>();
}
}
public interface IFileNameContainer
{
string FileName { get; }
}
public class LiveFileName : IFileNameContainer
{
public string FileName
{
get { return "live file name"; }
}
}
public class CustomerLoader
{
[Inject]
public ICustomerRepository CustomerRepository { get; set; }
private string _fileName;
// To get ninject to add the constructor parameter uncomment the line below
//public CustomerLoader(string fileName)
//{
// _fileName = fileName;
//}
public CustomerLoader(IFileNameContainer fileNameContainer)
{
_fileName = fileNameContainer.FileName;
}
public void LoadCustomer()
{
Customer c = CustomerRepository.GetCustomer();
Console.WriteLine(string.Format("Name:{0}\nAge:{1}\nFile name is:{2}", c.Name, c.Age, _fileName));
}
}
public interface ICustomerRepository
{
Customer GetCustomer();
}
public class CustomerRepository : ICustomerRepository
{
public Customer GetCustomer()
{
return new Customer() { Name = "Ciaran", Age = 29 };
}
}
public class Customer
{
public string Name { get; set; }
public int Age { get; set; }
}
}