I have implemented a custom OutputCacheProvider
public class MongoDBCacheProvider : OutputCacheProvider, IDisposable { ... }
The cacheprovider is registered like so:
<outputCache defaultProvider="MongoDBCacheProvider" enableOutputCache="true" >
<providers>
<add name="MongoDBCacheProvider" type="Mynamespace.Core.Caching.MongoDBCacheProvider, Mynamespace.Core" />
</providers>
</outputCache>
I need to pass some arguments to the constructor. I want to use Ninject to bind my cache provider.
this.Bind<System.Web.Caching.OutputCacheProvider>()
.To<Core.Caching.MongoDBCacheProvider>()
.WithConstructorArgument("databaseName", dbName);
More arguments have to be passed, but this is just an example. I'm sure simple solutions exist to somehow get that string there, but i would prefer to use Ninject like i use for all other classes.
This fails with the message: "No parameterless constructor defined for this object." The following binding doesn't work either.
this.Bind<Core.Caching.MongoDBCacheProvider>().ToSelf()
.InSingletonScope()
.WithConstructorArgument("databaseName", dbName);
I have verified that the binding runs before the error occurs. ASP .NET somehow bypasses the ninject bindings.
There doesn't seem to be any way to plug in a factory for it either.
Does anybody know how i can pass constructor arguments to a derived OutputCacheProvider?
Thank you.
You should be able to Inject into the object early in your web app life cycle by causing it to be injected during app startup.
NB you will have to use Property Setter Injection in preference to Constructor Injection, as there is likely no way to get the Cache Provider Provider to give you control of the instance creation.
See this blog post by #Remo Gloor
Related
I have a constructor that's getting its dependencies from a Dependency Injection framework (Autofac). The problem is I can not do anything else in the constructor except getting those dependencies, if I write any statement inside the constructor other than those dependency assignments, I get the following error:-
No parameter less constructor is defined for this object
I have to comment the assignment of readonly string shown below for this to work:-
public RelationshipController(ICustomerService customerService,)
{
this.customerService = customerService;
//someReadonlyString = "abcd";
}
Can somebody tell me, What's happening?
When the requested service (in this case, ICustomerService) cannot be found in the container, Autofac will move on to look for a default (a.ka. the parameterless) constructor. You obviously have no default constructor, thus Autofac bails out with an exception.
My guess is that the real error here is in the registration code for the ICustomerService interface.
I see a RelationshipController which probably means that you are using ASP.NET MVC. You probably didn't register Autofac correctly in MVC. In that case, MVC will not use Aufofac and can only work with default constructors.
Im a windsor noob and im having some problems getting dependency injection to work. im using a asp.net web application.
I have done the following
public interface IHandler{
...
}
public class Handler : IHandler{
...
}
then i try to register the code in global.asax application_start
container.Register(Component
.For(typeof(IHandler))
.ImplementedBy(typeof(Handler))
.Named("handler"));
When i want to use the Handler i create a property
public IHandler handler{get;set;}
but when i try to use it, it is null? why? am i missing someting?
Best regards
UPDATE
The only thing i doto register/resolve is the following:
container.Register(Component
.For(typeof(IHandler))
.ImplementedBy(typeof(Handler))
.Named("handler"));
and:
container.Resolve<IHandler>();
Do i need to do something else, Does it work to run this att application start?
UPDATE 2
Can the problem ocour because im trying to dependency inject on an ascx controll?
Make sure the component that has the IHandler property is also registered (and resolved) in Windsor.
You said this is for an ASP.NET application. The default lifestyle of Windsor components is singleton. Are you sure you want this component shared like that? You may want a transient or per-web-request lifestyle for this component.
Try removing the name from the registration, like this:
container.Register(Component
.For(typeof(IHandler))
.ImplementedBy(typeof(Handler)));
Alternatively, if you must name the component, you can use ServiceOverrides for the consuming class:
container.Register(Component
.For<SomeConsuer>()
.ServiceOverrides(new { handler = "handler" }));
If you are going to be registering several interfaces/services, then I recommend registering by convention (this is recommended in the docs). Consider this:
container.Register(
AllTypes.FromAssemblyNamed("Assembly")
.Where(Component.IsInNamespace("Assembly.Namespace"))
.WithService.DefaultInterface()
.Configure(c => c.LifeStyle.Transient));
This method performs matching based on type name and interface's name. More info Registering Components By Convention
This may be stupid question, but I am looking at Ninject sources and don't see NInject registering its own controller factory. I also don't see any IControllerFactory class in Ninject.Web.Mvc assembly. Am I missing something? How does Ninject create controller and inject parameters into constructor?
Lets say we are looking for "/Task/Index".
Ninject MVC applications use now DefaultControllerFactory, the same as non-Ninject applications.
DefaultControllerFactory finds type for controller (TaskController).
DefaultControllerFactory has internal class called DefaultControllerActivator. DefaultControllerActivator has method called Create, which returns controller instance. DefaultControllerFactory asks DefaultControllerActivator for TaskController type instance.
DefaultControllerActivator.Create uses IDependencyResolver. This is where Ninject comes in. Since Ninject implements its own resolver and sets it at the start of application, he gets request for TaskController instance.
The rest is easy. Ninject finds constructor for this type, injects parameters, returns controller instance.
MVC3 now recommends the usage of the IDependencyResolver interface instead of the good old IControllerFactory when dealing with DI. You can look at more details of this interface here.
This is the new Ninject class responsible for injecting the dependencies.
Since controllers are concrete types, Ninject will do self bind. Below is a snippet from ninject.complex.com
Bear in mind that only concrete types can be self-bound; abstract
types and interfaces won't work. Also, if you request an instance of a
type that can be self-bound, and there are no bindings defined for the
type, Ninject will automatically create an implicit self-binding. It's
up to you whether you want to define your bindings explicitly, or let
Ninject figure it out.
If you do need to inject parameters into the constructor. You can create a class inherits from INinjectModule and do the binding there.
I am wiring up my first SubSonic 3 application (in an ASP.NET MVC 1.0 front-end) and am looking at Rob's SimpleRepository. I'm using Castle.Windsor as an injection framework.
In my application startup, I configure Castle to bind a SubSonic SimpleRepository to a SubSonic IRepository. Nothing complicated there. However, the SimpleRepository has a ctor overload which takes two values: a connection string name and a set of SimpleRepositoryOptions. Not having dug too deep into Castle in the past, it's not clear if there is a way to specify the ctor arguments via configuration (or some other means).
Right now, I have a custom implementation of the SimpleRepository that explicitly creates a SimpleRepository with those arguments in it's parameterless ctor, but if I want to change these at any point in time, it requires changing the code and recompiling.
Is there a more elegant way to configure Castle to take constructor arguments?
If you're configuring Windsor using an XML file, you define your ctor arguments and their values like this:
<component id="repository" service="IRepository" type="SimpleRepository" ...>
<parameters>
<connectionString>your connection string</connectionString>
...
</parameters>
</component>
See the Windsor configuration reference for more info:
http://www.castleproject.org/container/documentation/v1rc3/manual/windsorconfigref.html
See this wiki page. What's called "parameters" on that page is either a constructor parameter (which is a required parameter) or a property (optional parameter)
I am a beginner using castle windsor; and kinda introduced to it with Apress Pro Mvc book. In the project that I am working at; I use castlewindsor controller factory instead of mvc controller factory; so i can have parametrized constructors and i can inject the dependencies.
Is there a way to tell the windsorcontroller factory to inject the values to the properties of the controller class without going through constructor?
The reason I want to do this is because I have Logging dependency; Emailler Dependency; Database Dependency; Theme Engine dEpendency; and I dont want to use this many parameters parameter in the constructor.
By default, when Windsor resolves a service implementation, it will populate all properties with public setters that it can satisfy.
However, take notice that sometime it does make sense to put the dependency resolving in the constructor, for that fact that it guarantees that any instance will always be in a valid state. Consider Unit Testing scenario, where the person writing the test will go crazy about the need to know which dependencies should be supplied. When all dependencies goes into the c'tor, the tester will have no choice but to supply the tested instance with all the required dependencies (as stubs or mocks).
Anyway, as for your question, Windsor support C'tor and property injection by default
Castle Windsor will automatically fill any properties with public setters that it knows how to fill.
This means if you have a class
public MyClass {
public SomeDependency {get; set;}
}
As long as the container is configured to know how to resolve SomeDependency it will attempt to resolve and inject it.
Sometimes I've found this default behavior to be hassle. This facility will give you finer grained control over the process.