In my MVC 5 app I am using Unity. Constructor injection is working fine as expected. Suppose I have a class which is not a controller and I have this setup for constructor injection, how can I configure Unity (code not xml) to tell it to use constructor injection when I new up an instance of my class. Is this possible?
My class is below:
public class Thing
{
private readonly IAuthorisationService _authorisationService;
public Thing()
{
}
public Thing(IAuthorisationService authorisationService)
{
_authorisationService = authorisationService;
}
public void Work()
{
var result = _authorisationService.IsAdmin(Guid.NewGuid());
}
}
So I am missing the bit where I tell unity to take over and inject when I new up a Thing.
Any ideas?
Assuming default Unity configuration all classes auto-registered with Unity, so the only thing you need is to call Resolve for your class on container.
var theThing = container.Resolve<Thing>();
Note that usually you get it happen magically by having dependency on Thing in your other classes (i.e. controllers).
If you need to create multiple instances of Thing - take dependency on Func<Thing> instead (which is also auto-registered and provides way to create instances resolved by container in the way you'd use new).
public MyController(Func<Thing> thingCreator)
{
var manyThings = Enumerable.Range(0, 9001).Select(()=> thingCreator());
...
}
Related
Suppose I have the following:
public class Test
{
public IDependency Dependency { get; set; }
}
IDependency and Test are registered in my Autofac builder. My IDependency resolution works fine, but what I'm trying to achieve is to be able to return new instances of Test in the code (e.g. return new Test();) and have it's IDependency properties prepopulated by Autofac.
What I've tried in my container:
builder.Register(x => new Test {
x.Resolve<IDependency>()
});
However, everytime I new Test() in the code, it's IDependency property is null. Is that possible?
(for reference, my train of thought leading to this attempt was that I initially did constructor injection for Test but then realized that in some cases I need to manually construct new Test() instances in the code, and couldn't figure out what to put to satisfy the constructor signature public Test(IDependency dependency) and still have Autofac resolve that dependency)
Just a thought - are you saying you need some mechanism to construct a new instance of the Test object (with it's dependencies injected) programatically in your code?
There's a handy feature built into Autofac to obtain factory for a registered type. I'd suggest you switch back to constructor injection:
public class Test
{
public Test(IDependency dependency)
{
Dependency = dependency;
}
public IDependency Dependency { get; }
}
and then register the types with Autofac as:
cb.ResisterType<MyDependency>().As<IDependency>();
cb.RegisterType<Test>();
Then all you need to do wherever you're wanting to manually construct a new instance of Test() is request a Func<Test> in your constructor. Autofac will generate a factory allowing you to instansiate a Test class whenever you like ... but without tight coupling to the Autofac library:
public class SomeAppLogic
{
public SomeAppLogic(Func<Test> testFactory)
{
// Some app logic
for (int i = 0; i < 10; i++)
{
// Invoke the testFactory to obtain a new instance
// of a Test class from the IoC container
Test newTestInstance = testFactory.Invoke();
}
}
}
Autofac refers to this as 'Dynamic Instantiation', which is covered here:
https://autofaccn.readthedocs.io/en/latest/resolve/relationships.html#dynamic-instantiation-func-b
I want to register two dependencies using constructors with parameters but I want only to make 'new' on the 'Dependency' class one time.
Instead of this:
builder.RegisterInstance(new ClassA(new Dependency())).As<IClassA>().SingleInstance();
builder.RegisterInstance(new ClassB(new Dependency())).AsSelf().SingleInstance();
I want something like this:
Dependency dependency = new Dependency();
builder.RegisterInstance(new ClassA(dependency)).As<IClassA>().SingleInstance();
builder.RegisterInstance(new ClassB(dependency)).AsSelf().SingleInstance();
If you register the dependency first it should automatically get passed to the new instances if they require it.
Assumptions:
public class ClassA : IClassA
{
public ClassA(Dependency dependency)
{
}
}
public class ClassB
{
public ClassB(Dependency dependency)
{
}
}
Then register dependency
var dependency = new Dependency();
builder.RegisterInstance(dependency).As<Dependency>();
builder.RegisterType<ClassA>().As<IClassA>().SingleInstance();
builder.RegisterType<ClassB>().AsSelf().SingleInstance();
Assuming that there is a reason you want to instantiate the type instead of registering it with Autofac which will do it for you then you should use Register instead of RegisterInstance.
builder.RegisterType<Dependency>().As<Dependency>().SingleInstance();
builder.Register(t => new ClassA(t.Resolve<Dependency>())).As<IClassA>().SingleInstance();
You can then use the passed in IComponentContext to resolve any required dependencies. Do keep in mind that with SingleInstance your instance is only created once so dependencies should be scoped similarly (don't expect a per request dependency to "renew" itself with every call to your singleton).
I've been using MVVM for WPF quite a while now but I've always been doing it this way:
ExampleView.xaml.cs (namespace: Example.Views)
public partial class ExampleView
{
public ExampleView()
{
InitializeComponent();
var viewModel = new ExampleViewModel();
DataContext = viewModel;
}
}
The ExampleView.xaml has no code concerning the ExampleViewModel except for bindings to properties.
ExampleViewModel.cs (namespace: Example.ViewModels)
public ExampleViewModel()
{
// No important code in here concerning this topic. Code here is only used in this class.
}
Below is a simplified MainWindowView.xaml.
<Window ...
xmlns:views="clr-namespace:Example.Views">
<Grid>
<views:ExampleView />
</Grid>
</Window>
The MainWindowView.xaml.cs is similar to the ExampleView.xaml.cs. The MainWindowViewModel.cs has no important code concerning this topic.
Lastly, the App.xaml contains the StartupUri="Views/MainWindowView.xaml".
If this is a good pattern or not, I got my application to work. Since the application is not maintainable by me alone anymore, 2-3 people are now working on it creating some problems. One person is doing the majority of the coding (ViewModels basically), one person is doing the GUI (Views) and one person is doing the "framework" coding. (Using "" because this is not really a framework but I can't think of a better word for it.)
Now, I'm the guy that is doing the framework coding and I've been reading up on several subjects like dependency injection and the code below is what I came up with using UnityContainer from Windows.
ExampleView.xaml.cs (namespace: Example.Views)
public partial class ExampleView
{
public ExampleView()
{
InitializeComponent();
}
}
The ExampleView.xaml has no code concerning the ExampleViewModel except for bindings to properties.
ExampleViewModel.cs (namespace: Example.ViewModels)
public string MyText { get; set; }
public ExampleViewModel(ILocalizer localizer)
{
MyText = localizer.GetString("Title");
}
Below is a simplified MainWindowView.xaml.
<Window ...
xmlns:views="clr-namespace:Example.Views">
<Grid>
<views:ExampleView DataContext="{Binding ExampleViewModel}" />
</Grid>
</Window>
The MainWindowView.xaml.cs is similar to the ExampleView.xaml.cs.
MainWindowViewModel.cs
ExampleViewModel ExampleViewModel { get; set; }
private readonly ILocalizer _localizer;
private readonly IExceptionHandler _exHandler;
public MainWindowViewModel(ILocalizer localizer, IExceptionHandler exHandler)
{
_localizer = localizer;
_exHandler = exHandler;
ExampleViewModel = new ExampleViewModel(localizer);
}
Lastly, the App.xaml does not contains the StartupUri="..." anymore. It's now done in App.xaml.cs. It's also here where the `UnityContainer is initialized.
protected override void OnStartup(StartupEventArgs e)
{
// Base startup.
base.OnStartup(e);
// Initialize the container.
var container = new UnityContainer();
// Register types and instances with the container.
container.RegisterType<ILocalizer, Localizer>();
container.RegisterType<IExceptionHandler, ExceptionHandler>();
// For some reason I need to initialize this myself. See further in post what the constructor is of the Localizer and ExceptionHandler classes.
container.RegisterInstance<ILocalizer>(new Localizer());
container.RegisterInstance<IExceptionHandler>(new ExceptionHandler());
container.RegisterType<MainWindowViewModel>();
// Initialize the main window.
var mainWindowView = new MainWindowView { DataContext = container.Resolve<MainWindowViewModel>() };
// This is a self made alternative to the default MessageBox. This is a static class with a private constructor like the default MessageBox.
MyMessageBox.Initialize(mainWindowView, container.Resolve<ILocalizer>());
// Show the main window.
mainWindowView.Show();
}
For some reason I need to initialize the Localizer and ExceptionHandler classes myself. The Localizer and ExceptionHandler constructors are found below. Both have constructors with all arguments that have a default value. Adding constructors without arguments like
public ExceptionHandler() : this(Path.Combine(Directory.GetCurrentDirectory(), "ErrorLogs", DateTime.Now.ToString("dd-MM-yyyy") + ".log")) { }
doesn't change a thing.
public Localizer(ResourceDictionary appResDic = null, string projectName = null, string languagesDirectoryName = "Languages", string fileBaseName = "Language", string fallbackLanguage = "en")
{
_appResDic = appResDic ?? Application.Current.Resources;
_projectName = !string.IsNullOrEmpty(projectName) ? projectName : Application.Current.ToString().Split('.')[0];
_languagesDirectoryName = languagesDirectoryName.ThrowArgNullExIfNullOrEmpty("languagesFolder", "0X000000066::The languages directory name can't be null or an empty string.");
_fileBaseName = fileBaseName.ThrowArgNullExIfNullOrEmpty("fileBaseName", "0X000000067::The base name of the language files can't be null or an empty string.");
_fallbackLanguage = fallbackLanguage.ThrowArgNullExIfNullOrEmpty("fallbackLanguage", "0X000000068::The fallback language can't be null or an empty string.");
CurrentLanguage = _fallbackLanguage;
}
public ExceptionHandler(string logLocation = null, ILocalizer localizer = null)
{
// Check if the log location is not null or an empty string.
LogLocation = string.IsNullOrEmpty(logLocation) ? Path.Combine(Directory.GetCurrentDirectory(), "ErrorLogs", DateTime.Now.ToString("dd-MM-yyyy") + ".log") : logLocation;
_localizer = localizer;
}
My big question now is if I'm approaching dependency injection correctly and if having several static classes that I initialize once are bad. Several topics I've read state that static classes are a bad-practice because of bad testability and tightly coupled code, but right now the tradeoffs of dependency injection are bigger than having static classes.
Doing dependency injection correctly would be a first step in having less tightly coupled code though. I like the approach with the static MyMessageBox I can initialize once and that it's globally available in the application. This is mainly for "easy usage" I guess cause I can simply call MyMessageBox.Show(...) instead of injecting this all the way down to the smallest element. I have a similar opinion about the Localizer and ExceptionHandler because these will be used even more.
A last concern I have is the following. Lets say I have a class with several arguments and one of the arguments is the Localizer (because this will be used in nearly any class). Having to add ILocalizer localizer every time
var myClass = new MyClass(..., ILocalizer localizer);
feels very annoying. This would push me towards a static Localizer I initialize once and having never to care about it anymore. How would this problem be tackled?
If you have a bunch of "Services" which are used in many classes, you can create a facade class which encapsulates the required services and inject the facade into your classes.
Advantage of doing so is, you can easily add other services to that facade and they'd be available in all other injected classes, without modifying the constructor parameters.
public class CoreServicesFacade : ICoreServicesFacade
{
private readonly ILocalizer localizer;
private readonly IExceptionHandler excaptionHandler;
private readonly ILogger logger;
public ILocalizer Localizer { get { return localizer; } }
public IExceptionHandler ExcaptionHandler{ get { return exceptionHandler; } }
public ILogger Logger { get { return logger; } }
public CoreServices(ILocalizer localizer, IExceptionHandler exceptionHandler, ILogger logger)
{
if(localizer==null)
throw new ArgumentNullException("localizer");
if(exceptionHandler==null)
throw new ArgumentNullException("exceptionHandler");
if(logger==null)
throw new ArgumentNullException(logger);
this.localizer = localizer;
this.exceptionHandler = exceptionHandler;
this.logger = logger;
}
}
Then you can pass it to your classes:
var myClass = new MyClass(..., ICoreServicesFacade coreServices);
(which you shouldn't do anyway when using Dependency Injection, you shouldn't use new keyword, except for factories and models).
As for your ILocalizer and IExceptionHandler implementations... if your ExceptionHandler requires the Localizer and the localizer requires the string parameter, you have two options, depending on if the file name needs to be determined at a later point at run time or only once during the Application initialization.
Important
Don't use optional constructor parameters if you want to use dependency injection. For DI, constructor parameters should declare the dependencies in constructor and constructor dependencies are always considered as mandatory (don't use ILocalizer localizer = null within the constructor).
If you only create the logfile during the Applications initialization, it's quite easy
var logFilePath = Path.Combine(Directory.GetCurrentDirectory(), "ErrorLogs", DateTime.Now.ToString("dd-MM-yyyy") + ".log");
var localizer = new Localizer(...);
var exceptionHandler = new ExceptionHandler(logFilePath, localizer);
container.RegisterInstance<ILocalizer>(localizer);
container.RegisterInstance<IExceptionHandler>(exceptionHandler);
Basically in your bootstrapper you instantiate and configure your Localizer and ExceptionHandler, then register it as instance with the container.
If for some reason, you need to determine the name of log filename or language at a later point (after Bootstrapper configuration & initialization), you need to use a different approach: You need a factory class.
The factory will be injected into your classes rather than the instance of ILocalizer/IExceptionHandler and create the instance of it when the parameters are known.
public interface ILocalizerFactory
{
ILocalizer Create(ResourceDictionary appResDic, string projectName);
}
public class ILocalizerFactory
{
public ILocalizer Create(ResourceDictionary appResDic, string projectName)
{
var localizer = new Localizer(appResDic, projectName, "Languages", "Language", "en");
return localizer;
}
}
Using the facade Example from above:
public class CoreServicesFacade : ICoreServicesFacade
{
private readonly ILocalizer localizer;
public ILocalizer Localizer { get { return localizer; } }
public CoreServices(ILocalizerFactory localizerFactory, ...)
{
if(localizer==null)
throw new ArgumentNullException("localizerFactory");
this.localizer = localizerFactory.Create( Application.Current.Resources, Application.Current.ToString().Split('.')[0]);
}
}
Caveats & tips
Move Default configuration outside of the classes itself
Don't use such code inside your Localizer/ExceptionHandler classes.
_appResDic = appResDic ?? Application.Current.Resources;
_projectName = !string.IsNullOrEmpty(projectName) ? projectName : Application.Current.ToString().Split('.')[0];
_languagesDirectoryName = languagesDirectoryName.ThrowArgNullExIfNullOrEmpty("languagesFolder", "0X000000066::The languages directory name can't be null or an empty string.");
_fileBaseName = fileBaseName.ThrowArgNullExIfNullOrEmpty("fileBaseName", "0X000000067::The base name of the language files can't be null or an empty string.");
_fallbackLanguage = fallbackLanguage.ThrowArgNullExIfNullOrEmpty("fallbackLanguage", "0X000000068::The fallback language can't be null or an empty string.");
CurrentLanguage = _fallbackLanguage;
This pretty much makes it untestable and puts the configuration logic in the wrong place. You should only accept and validate the parameters passed into the constructor and determine the values and fall backs in either a) factory's create method or b) inside your bootstrapper (if runtime parameters aren't required).
Don't use View-related type inside your interfaces
Don't use ResourceDictionary in your public interfaces, this will leak View knowledge into your ViewModels and require you to have a reference to the assembly containing View/Application related code (I know I used it above, based on your Locator constructor).
If you need it, pass it as constructor Parameter and implement the class in Application/View assembly, while having your Interface in your ViewModel assembly). Constructors are implementation detail, and can be hidden (by implementing the class in a different assembly which allows reference to the class in question).
Static classes are evil
As you already realized, static classes are bad. Inject them is the way to go. Your Application will most likely need a navigation too. So you can put Navigation (Navigate to a certain View), MessageBoxes (display an information) and opening of new Windows (a kind of navigation too) into either one service or a navigation facade (similar to above one) and pass all services related to navigation as a single Dependency into your objects.
Passing parameters to ViewModel
Passing parameters can be a bit of a pain in "home-brew" frameworks and you shouldn't pass parameters via ViewModel constructors (prevents DI from resolving it or forcing you to use a factory). Instead consider writing a navigation service (or using exiting framework). Prims has it solved pretty nicely, you got a navigation service (which will do the navigation to a certain View and it's ViewModel and also offers INavigationAware interface with NavigateTo and NavigateFrom methods, which are called when one navigates to a new view (one of this methods parameters can be used to provide parameters to the ViewModel) and when navigating from a ViewModel (i.e. to determine if navigating from a view is viable or to cancel the navigation if necessary, for example: Asking the user to save or discard the data before navigating to the other ViewModel).
But that's bit off-topic.
Example:
public class ExampleViewModel : ViewModelBase
{
public ExampleViewModel(Example2ViewModel example2ViewModel)
{
}
}
public class Example2ViewModel : ViewModelBase
{
public Example2ViewModel(ICustomerRepository customerRepository)
{
}
}
public class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel(ExampleViewModel example2ViewModel)
{
}
}
// Unity Bootstrapper Configuration
container.RegisterType<ICustomerRepository, SqlCustomerRepository>();
// You don't need to register Example2ViewModel and ExampleViewModel unless
// you want change their container lifetime manager or use InjectionFactory
To get an resolve instance of your MainWindowViewModel simply do
MainWindowViewModel mainWindowViewModel = container.Resolve<MainWindowViewModel>();
and Unity will resolve all other dependencies (it will inject ICustomerRepository into Example2ViewModel, then inject Example2ViewModel into ExampleViewModel and finally inject ExampleViewModel into your MainWindowViewModel and return an instance of it.
The catch is: You can't use the container inside your ViewModels (though using it in View's code-behind is okay in your use case. However it's better to use navigation Service or a ViewModel Locator within your XAML (see Prism on how they did it)) .
So you need a navigation service of a kind, if you need to do it from ViewModels.
I have been helping a few friends on a project and there is a class that uses Ninject. I am fairly new to C# and I have no idea what that class is doing, which is why I need to understand Ninject. Can anyone explain what Ninject is and when does one use it(with example if possible)? Or if you can point to some links that would be great too.
I tried this question: Ninject tutorials/documentations? but it didn't really help a beginner like me.
Ninject is dependency injector for .NET, practical realisation of pattern Dependency Injection (form of Inversion of Control pattern).
Suppose you have two classes DbRepository and Controller:
class Controller {
private DbRepository _repository;
// ... some methods that uses _repository
}
class DbRepository {
// ... some bussiness logic here ...
}
So, now you have two problems:
You must initialize _repository to use it. You have several options for doing this:
Manually, within the constructor. But what if the constructor of DbRepository changes? You would need to rewrite your Controller class because code it's dependent upon was changed. It's not hard if you have only one Controller, but if you have a couple of classes that have a dependency on your Repository you have a real problem.
You can use a service locator or factory. But now you have a dependency on your service locator. You have a global service locator and all code must use it. How you will you change the behavior of your service locator when you need to use it in one part of your code for activation logic but for something else in another part of your code? There is only one way - passing the service locator through constructors. But with more and more classes you will need to pass it more and more times. Anyway, it's a good thought but in the long run, it's a bad idea.
class Controller {
private DbRepository _repository;
public Controller() {
_repository = GlobalServiceLocator.Get<DbRepository>()
}
// ... some methods that uses _repository
}
You can use dependency injection. Look at the code:
class Controller {
private IRepository _repository;
public Controller(IRepository repository) {
_repository = repository;
}
}
Now when you need your controller you write: ninjectDevKernel.Get<Controller>(); or ninjectTestKernel.Get<Controller>();. You can switch beetween dependency resolvers as fast as you want. See? It's simple, you don't need to write a lot.
You can't create unit tests for it. Your Controller has a dependency on DbRepository and if you want to test some method that uses repository, your code will go to the database and ask it for data. That's slow, very slow. If your code in DbRepository changes, your unit test on Controller will fall. Only integration test must warn you of 'problems' in this case. What you need in unit tests - is to isolate your classes and test only one class in one test (in ideal - only one method). If your DbRepository code fails, you will think that Controller code failed - and that's bad (even if you have tests for DbRepository and Controller - they both will fail and you can start from the wrong place). It takes a lot of time to determine where the error really is. You need to know that class A is ok, and it was class B where something failed.
When you want to replace DbRepository with something else in all your classes, you have to do a lot of work.
You can't easily control the lifetime of DbRepository. An object of this class is created on initialization of Controller and deleted when Controller is deleted. There is no sharing between different instances of the Controller class and there is no sharing between other classes. With Ninject you can simply write:
kernel.Bind<IRepository>().To<DbRepository>().InSingletonScope();
A special feature of dependency injection - agile development! You describe that your controller uses a repository with interface IRepository. You don't need to write DbRepository, you can simply create a MemoryRepository class and develop Controller while another person develops DbRepository. When work on DbRepository is finished, you just rebind in your dependency resolver that default IRepository is now DbRepository. Have a lot of controllers? All of them will now use DbRepository. That's cool.
Read more:
Inversion of control (wiki)
Dependency injection (wiki)
Inversion of Control Containers and the Dependency Injection pattern (Martin Fowler)
Ninject is an Inversion of Control container.
What does it do?
Suppose you have a Car class that depends on a Driver class.
public class Car
{
public Car(IDriver driver)
{
///
}
}
In order to use the Car class you build it like so:
IDriver driver = new Driver();
var car = new Car(driver);
A IoC containter centralizes the knowledge about how to build classes. It is a central repository that knows a few things. For example, it knows that the concrete class that you need to use to build a car is a Driver and not any other IDriver.
For example, if you are developing a MVC application, you can tell Ninject how to build your controllers. You do so by registering which concrete classes satisfy specific interfaces. At run time Ninject will figure out which classes are needed to build the required controller, and all behind the scenes.
// Syntax for binding
Bind<IDriver>().To<Driver>();
This is beneficial because it lets you build systems that are more easily unit testable. Suppose that Driver encapsulates all database access for Car. In a unit test for Car you can do this:
IDriver driver = new TestDriver(); // a fake driver that does not go to the db
var car = new Car(driver);
There are entire frameworks that take care of automatically creating testing classes for you and they are called mocking frameworks.
For more information:
GitHub/Ninject Home
Inversion of Control
Inversion of Control Containers and the Dependency Injection pattern
Mock Object
Other answers are great but I would also like to point out this Implementing Dependency Injection using Ninject article.
This is one of the best articles I ever read which explains Dependency Injection and Ninject with a very elegant example.
Here's the snippet from the article:
Below Interface will be implemented by our (SMSService) and (MockSMSService), basically the new Interface (ISMSService) will expose the same behaviors of both services as the code below:
public interface ISMSService
{
void SendSMS(string phoneNumber, string body);
}
(SMSService) implementation to implement the (ISMSService) interface:
public class SMSService : ISMSService
{
public void SendSMS(string mobileNumber, string body)
{
SendSMSUsingGateway(mobileNumber, body);
}
private void SendSMSUsingGateway(string mobileNumber, string body)
{
/*implementation for sending SMS using gateway*/
Console.WriteLine("Sending SMS using gateway to mobile:
{0}. SMS body: {1}", mobileNumber, body);
}
}
(MockSMSService) with totally different implementation using the same interface:
public class MockSMSService :ISMSService
{
public void SendSMS(string phoneNumber, string body)
{
SaveSMSToFile(phoneNumber,body);
}
private void SaveSMSToFile(string mobileNumber, string body)
{
/*implementation for saving SMS to a file*/
Console.WriteLine("Mocking SMS using file to mobile:
{0}. SMS body: {1}", mobileNumber, body);
}
}
we need to implement a change to our (UIHandler) class constructor to pass the dependency through it, by doing this, the code which uses the (UIHandler) can determine which concrete implementation of (ISMSService) to use:
public class UIHandler
{
private readonly ISMSService _SMSService;
public UIHandler(ISMSService SMSService)
{
_SMSService = SMSService;
}
public void SendConfirmationMsg(string mobileNumber) {
_SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
}
}
Now, we have to create a separate class (NinjectBindings) which inherits from (NinjectModule). This class will be responsible to resolve dependencies at run time, then we’ll override the load event which is used to configure the binding in it. The nice thing about Ninject is that we do not need to change our code in (ISMSService), (SMSService), and (MockSMSService).
public class NinjectBindings : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<ISMSService>().To<MockSMSService>();
}
}
Now in UI form code, we’ll use the binding for Ninject which will determine which implementation to use:
class Program
{
static void Main(string[] args)
{
IKernel _Kernal = new StandardKernel();
_Kernal.Load(Assembly.GetExecutingAssembly());
ISMSService _SMSService = _Kernal.Get<ISMSService>();
UIHandler _UIHandler = new UIHandler(_SMSService);
_UIHandler.SendConfirmationMsg("96279544480");
Console.ReadLine();
}
}
Now the code is using the Ninject Kernal to resolve all chain of dependencies, if we want to use the real service (SMSService) in Release mode (on production environment) instead of the mock one, we need to change on the Ninject binding class (NinjectBindings) only to use the right implementation or by using the #if DEBUG directive as below:
public class NinjectBindings : Ninject.Modules.NinjectModule
{
public override void Load()
{
#if DEBUG
Bind<ISMSService>().To<MockSMSService>();
#else
Bind<ISMSService>().To<SMSService>();
#endif
}
}
Now our binding class (NinjectBindings) is living on the top of all our execution code and we can control the configuration easily in once place.
Also, see What is Inversion of Control? some very simple examples are mentioned to understand IoC.
You have to understand the Dependency Injection(DI) first. Notice here,
public interface IService
{
void Serve();
}
public class Service1 : IService
{
public void Serve() {
Console.WriteLine("Service1 Called");
}
}
public class Service2 : IService
{
public void Serve() {
Console.WriteLine("Service2 Called");
}
}
public class Service3 : IService
{
public void Serve() {
Console.WriteLine("Service3 Called");
}
}
public class Client
{
private IService service;
public Client(IService _service) //Constructor injection
{
service = _service;
}
public void ServeMethod() {
service.Serve(); //Notice here, this Serve() method has no idea what to do.
} // runtime will assign the object, that is Ninject
}
class Program
{
static void Main(string[] args)
{
IService s1 = new Service1(); //N.B. Ninject assigns object with interface
Client c1 = new Client(s1);
c1.ServeMethod();
IService s2 = new Service2(); //N.B. Ninject assigns object with interface
c1 = new Client(s2);
c1.ServeMethod();
IService s3 = new Service3(); //N.B. Ninject assigns object with interface
c1 = new Client(s3);
c1.ServeMethod();
Console.ReadKey();
}
}
// Ninject creates object in runtime for interface in runtime in ASP.NET MVC project.
/*
Output:
Service1 Called
Service2 Called
Service3 Called
*/
I need some help - I am trying to use a custom validation attribute in an ASP.NET MVC web project that needs to make a database call.
I have windsor successfully working for the controllers and the IRepository interface is injected normally. The problem arrises when I need to inject the repository into the attribute class.
The attribute class has the following code:
public class ValidateUniqueUrlNodeAttribute : AbstractValidationAttribute
{
private readonly string message;
private readonly IArticleRepository articleRepository;
public ValidateUniqueUrlNodeAttribute(string message)
{
this.message = message;
}
public ValidateUniqueUrlNodeAttribute(string message, IArticleRepository articleRepository):this(message)
{
this.articleRepository = articleRepository;
}
public override IValidator Build()
{
var validator = new UniqueUrlNodeValidator(articleRepository) { ErrorMessage = message };
ConfigureValidatorMessage(validator);
return validator;
}
My problem is that I cannot seem to make Windsor intercept the contruction of the attribute to pass in the IArticleRepository
The current code in my global.asax file is as follows:
container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
container
.RegisterControllers(Assembly.GetExecutingAssembly())
.AddComponent<IArticleRepository, ArticleRepository>()
.AddComponent<ValidateUniqueUrlNodeAttribute>();
Any help would be greatly appreciated.
AFAIK no dependency injection container can directly manage an attribute, since it's instantiated by the runtime and there's no way to intercept that.
However, they can cheat by either:
Using a static gateway to the container (example), or
Using a "BuildUp" feature that injects whatever dependencies are found within an already-constructed object. This is called BuildUp in Unity or InjectProperties in Autofac.
Windsor doesn't support #2 (ref1, ref2), so you can either:
Try one of the hacks to make Windsor support #2 (hack1, hack2)
Use a static gateway
Implement your own IValidatorBuilder and make it use Windsor to create validators. I'm sure this is implemented somewhere but I can't find it right now...
Don't know if this helps, but I subclassed ValidationAttribute to expose a Resolve<T>() method like so:
public abstract class IocValidationAttribute : ValidationAttribute
{
protected T Resolve<T>()
{
return IocHelper.Container().Resolve<T>();
}
}
Then it can be used in any custom ValidatorAttribute that needs to hit a database:
public class UniqueEmailAttribute : IocValidationAttribute
{
public override bool IsValid(object value)
{
ICustomerRepository customerRepository = Resolve<ICustomerRepository>();
return customerRepository.FindByEmail(value.ToString()) == null;
}
}
I think it's a variation of the 'Static Gateway' approach mentioned by Mauricio Scheffer. I don't know if this is a good design or not. I'm not a huge fan of it, I'd rather the dependency was injected more 'elegantly', though I can't use constructor injection obviously, I'd like to use Property injection but can't work out a way to hook into the ASP.NET MVC framework code to do this (I've even pored though the MVC2 source code).
I was able to wire it up [using Autofac as it happens, but it's just constructor injection via the ASP.NET MVC DependencyResolver] in this answer, enabling one to write:
class MyModel
{
...
[Required, StringLength(42)]
[ValidatorService(typeof(MyDiDependentValidator), ErrorMessage = "It's simply unacceptable")]
public string MyProperty { get; set; }
....
}
public class MyDiDependentValidator : Validator<MyModel>
{
readonly IUnitOfWork _iLoveWrappingStuff;
public MyDiDependentValidator(IUnitOfWork iLoveWrappingStuff)
{
_iLoveWrappingStuff = iLoveWrappingStuff;
}
protected override bool IsValid(MyModel instance, object value)
{
var attempted = (string)value;
return _iLoveWrappingStuff.SaysCanHazCheez(instance, attempted);
}
}
With some helper classes (look over there), you wire it up e.g. in ASP.NET MVC like so in the Global.asax :-
DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(
typeof(ValidatorServiceAttribute),
(metadata, context, attribute) =>
new DataAnnotationsModelValidatorEx(metadata, context, attribute, true));
Hmm.
Can you test the effect of removing the (string message) ctor, and see if that at least forces Castle to use the ctor with the Repostiory ?
Otherwise we call AddComponent(name, type, type). Other than that it really should work...
Also does this hint at my first idea ? How do I use Windsor to inject dependencies into ActionFilterAttributes