I have an MVC4 application using StructureMap.MVC4. Here's a fragment of IoC.cs
ObjectFactory.Initialize(x =>{
x.Scan(scan =>{
scan.TheCallingAssembly();
scan.WithDefaultConventions();});
x.For<IDbContext>().Use<EfDbContext>().Ctor<string>("connectionStringName").Is("DefaultDb");
x.For<IDatabase>().Use<Database>().Ctor<string>("connectionStringName").Is("DefaultDb");
x.For<IActionInvoker>().Use<InjectingActionInvoker>();
x.SetAllProperties(c=>c.OfType<IDbContext>());
... ...
DbContext injection works fine, so does the setter injection for ActionFilters, as well as all Service:IService using default convention. But I got the following error trying to inject IDatabase:
Could not find a constructor parameter or property for NPoco.Database, NPoco, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null named connectionStringName Parameter name: name
If I change it to
x.For<IDatabase>().Use(new Database("DefaultDb"));
It works. Any ideas why? I wonder if by using New, it will end up a different instance of IDatabase, especially when mixing with the IDbContext instance. Thanks.
Seems related to StructureMap can't decide the default constructor when there are multiples with similar constructor parameters. In this case, it has
Database(string connectionStringName)
Database(string connectionStringName, string Provider)
....
Looks like this is slight better syntax?
x.For<IDatabase>().Use(() => new Database("DefaultDb"));
Related
In razor pages I'm using #inject Blazored.LocalStorage.ISyncLocalStorageService localStorage and it's working fine. But from non-razor connected classes (services and helpers) using
[Inject]
protected Blazored.LocalStorage.ISyncLocalStorageService localStorage { get; set; }
Always returns null. Is there something additional that is needed to get DI to work in non-Razor files? Or do I have to push all of the DI through Constructors all the way down from the UI layer?
The following is based only on my own experience, so I might be proved wrong...
Only constructor injection works in non-razor objects. Thus you cannot define a property annotated with the Inject attribute and expect it to be populated with an instance of a given object. Use constructor injection instead.
With Razor objects, however, you can use the #inject directive to inject services into Razor components, but you can also use the Inject attribute with properties in razor component class definition (.razor.cs ) and in #code blocks ( .razor ).
Hope this helps...
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
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
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)