I'm working on a WCF service that uses a duplex channel to allow the service to call back to the client to relay an event raised by a component in the service layer. The proxy class is defined and constructed like this:
public class EvsMembershipProxy : DuplexClientBase<IMembershipProviderCallback>, IEvsMembershipProvider
{
public EvsMembershipProxy(InstanceContext callbackInstance): base(callbackInstance)
{
}
}
I need to get an instance of this class in a class that is configured using the ASP.NET membership system, so I bind it like this:
_ninjectKernal.Bind<IEvsMembershipProvider>().To<EvsMembershipProxy>();
and I inject it like this:
public class EvsMembershipProvider : MembershipProvider, IMembershipProviderCallback
{
#region "Dependencies"
[Inject]
public IEvsMembershipProvider MembershipProvider { get; set; }
#endregion
}
The configured membership provider is injected by Ninject like this:
_ninjectKernal.Inject(System.Web.Security.Membership.Provider);
_ninjectKernal.Inject(System.Web.Security.Roles.Provider);
I have tested the injection pattern with the WCF service layer without the duplex service and it works correctly. However, when I include the duplex service, Ninject fails during binding with the following error:
Error activating ServiceHostBase
No matching bindings are available, and the type is not self-bindable.
Activation path:
4) Injection of dependency ServiceHostBase into parameter host of constructor of type InstanceContext
3) Injection of dependency InstanceContext into parameter callbackInstance of constructor of type EvsMembershipProxy
2) Injection of dependency IEvsMembershipProvider into property MembershipProvider of type EvsMembershipProvider
1) Request for EvsMembershipProvider
Suggestions:
1) Ensure that you have defined a binding for ServiceHostBase.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
So it looks as though I will need a binding for the ServiceHostBase class used in the EvsMembershipProxy constructor to resolve this issue. However, I don't know how to configure it. My best attempt to resolve the ServiceHostBase binding so far has been:
_ninjectKernal.Bind<ServiceHostBase>().ToMethod(c => OperationContext.Current.Host);
However this fails with a null reference exception during binding.
How do I bind the ServiceHostBase type so that this injection works?
** EDIT: simplified the original code to remove some of the EvsMembershipProxy constructor arguments which could be supplied by WCF configuration **
Discovered I could configure it like this.
_ninjectKernal.Bind<IEvsMembershipProvider>()
.To<EvsMembershipProxy()
.WithConstructorArgument("callbackInstance", Membership.Provider);
The configured membership provider implements the IMembershipProviderCallback interface and receives the callback from the service.
Related
I'm creating a project soon to be a nuget. There is a public class where I inject a class whose visibility modifier is internal, but the compiler states:
Inconsistent accessibility: parameter type 'blah' is less accessible than method 'bleh'
I don't want to expose the rest of the project classes to the rest of the world. Is it possible to do?
AuthenticationContext resolution:
You can inject IServiceProvider and get your service like
var authContext = _serviceProvider.GetService<AuthenticationContext>();
or you need to change accessibility of your method
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.
I'm trying to inject a repository to a custom membership provider with ninject in MVC 3.
In MembershipProvider I have tried the following:
[Inject]
public ICustomerRepository _customerRepository{ get; set; }
And
[Inject]
public TUMembershipProvider(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
In my ninject module i tried the following:
Bind<MembershipProvider>().ToConstant(Membership.Provider);
None of the above works.
When i use(in global.asa)
kernel.Inject(Membership.Provider);
together with
[Inject]
public ICustomerRepository _customerRepository{ get; set; }
it works, but i have no life cycle management and this will cause a "ISession is open" error from NHibernate, because the ISession is InRequestScope and the repository is not.
You could use the approach #Remo Gloor outlines in his blog post on provider injection. It involves 3 steps:
Add [Inject]s to any properties on your provider you need injected (although the pattern he shows -- creating a very simple class whose only function is to be a receptable for property injection and forwards any requests to a real class implemented using constructor injection -- is well worth following)
public class MyMembershipProvider : SqlMembershipProvider
{
[Inject]
public SpecialUserProvider SpecialUserProvider { get;set;}
...
Create an initializer wrapper that implements IHttpModule which pulls the provider in, triggering its creation:-
public class ProviderInitializationHttpModule : IHttpModule
{
public ProviderInitializationHttpModule(MembershipProvider membershipProvider)
{
}
...
Register the IHttpModule in your RegisterServices :-
kernel.Bind<IHttpModule>().To<ProviderInitializationHttpModule>();
there is no 4; Ninject does the rest - bootstrapping all registered IHttpModules including the one you added) during the startup sequence.
(Don't forget to read the comments on the blog post re lifetimes etc.)
Finally, if you're looking for something completely braindead direct that solves it neatly, try this #Remo Gloor answer instead
PS a great writeup on the whole mess is Provider is not a Pattern by #Mark Seemann. (and the oboligatory plug for his excellent book:- Dependency injection in .NET which will have you figuring this stuff out comfortably from first principles)
i had this problem
a custom membership, role and profile provider in another project from MVC using repository, when ever i call the provider the injected repository was null.
tried to call kernel.Inject(Membership.Provider); in the NinjectWebCommon method registerServices(IKernel kernel) but got the exception
The result is always null, because asp.net has it's own static property for membership.which is membership.provider. and this instance is not part of instance ninject management.
so use on PostApplicationStartMethod
here is the soloution by cipto add to NinjectWebCommon the attrbute and method :
[assembly: WebActivator.PreApplicationStartMethod(typeof(WebApp.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.PostApplicationStartMethod(typeof(WebApp.App_Start.NinjectWebCommon), "RegisterMembership")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(WebApp.App_Start.NinjectWebCommon), "Stop")]
public static void RegisterMembership()
{
bootstrapper.Kernel.Inject(Membership.Provider);
}
The problem is that the whole Membership infrastructure is a "native" .NET code (System.Web.Security) that does not know about MVC and about the DI container used by MVC.
The static call to Membership.Provider returns the membership provider based on the configuration, however, the specified provider type is instantiated with a simple Activator.CreateInstance call. Hence, the dependency injection has no chance to kick in and set your repository dependency on the result. If you explicitly setup the returned instance with Ninject it can work, because you explicitly gave Ninject the object to set the dependencies. Even in this case it can only work with property injection and not with constructor injection, because the instance is created by the membership configuration previously.
To summarize: you cannot easily inject dependencies into the membership provider because it is not resolved from a dependency injection container.
I think you have 2 possibilities:
You create a repository in the custom membership provider directly or you access it by some other means on demand (where the web context is already present).
You go one level higher and check the components that would use your membership provider and you try change there (to use a membership provider resolved from your DI container instead of the uninitialized Memership.Provider). If this "higher component" is the forms authentication, then this article might be of help (using dependency injection with IFormsAuthentication and IMembershipService): http://weblogs.asp.net/shijuvarghese/archive/2009/03/12/applying-dependency-injection-in-asp-net-mvc-nerddinner-com-application.aspx
Did you try resolving your repository "manually", like in this answer:
Ninject : Resolving an object by type _and_ registration name/identifier
?
I am using an IoC container that uses constructor injection (Castle Windsor, for example). I have the following (example) class which manages a product...
public class ProductDataManager
{
public ProductDataManager(Product product, IProductDataLoader productDataLoader)
{
}
// a number of methods here that manage the products data in different ways...
}
It has a dependency on a Product which is only known by the classes consumer. It also has a dependency on a product data loader service. I define the implementer of this service in the IoC container.
How do I define this class (ProductDataManager) in the IoC container (and/or the consuming class) so that the service dependency (IProductDataLoader) can be injected by the IoC container and the data dependency (Product) can be passed by the consuming class?
Or is this a code smell? If so, how can this be modified?
You can use the TypedFactoryFacility and do something like this (off the top of my head)... first, define an interface for your abstract factory:
public interface IProductDataManagerFactory
{
ProductDataManager Create(Product product);
}
Register the factory like so:
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IProductDataManagerFactory>().AsFactory());
Now services can depend on IProductDataManagerFactory and have Windsor invoke container.Resolve through an automagically implemented factory.
Note that the parameter name product in the method signature must correspond to the parameter name in the ctor of ProductDataManager.
I want to use Ninject in my Windows application and I want to know if there is best practices that I can do; strategies to find a balance between performance and maintenance.
The problem with Windows application and Web application is that in Web application, there is a scope easy to define that is the context but with Windows application, you have no scope that is easy to use form after form.
As example, I have a service that query the database. This service have a constructor and received a UnitOfWork. With Ninject, I can create a property marked as to be injected but if I do that, each time I will create this service, a new connection will be created to the database.
Just for this reason, I must manually create my services to control the number of connection created and no dependency injector can be used.
I have found that you can call the Inject method after created the service for inject dependencies but I'm sure I can use a better strategy.
With Ninject, you can have Ninject scope lifetimes of your injected dependencies to any object you want to provide (not just Singleton, Request, Thread, and Transient scopes).
From the Ninject Documentation Wiki:
You can also easily define you own
scopes using the .InScope(object o)
method.
You'll find some actual detail about how object scoping works in this Ninject Google Groups question & answer.
I finally found what I searching for.
Create a class that inherits from 'Ninject.Activation.Provider(of T)'
Overrrides the function 'CreateInstance'
Bind your interface with that 'Bind(Of [Your interface]).ToProvider([Your provider class])'
And now, you will be able to control each instance created that are associated with the specified interface.
Note that you can pass a type or an instance to the provider parameter of the Bind method. You can with an instance create a provider before binding your interfaces and use this provider in your code when you want to create a new instance.
The provider in conjunction with InScope allows great flexibility for each place where you want to have and instance of an object that can be injected automatically and have a determined scope.
Here is an example:
Public Interface IConnection
End Interface
Public Class Connection
Implements IConnection
End Class
Imports Ninject
Public Class StandardModule
Inherits Ninject.Modules.NinjectModule
Public Property ConnectionProvider As ConnectionProvider
Public Overrides Sub Load()
Bind(Of IConnection).ToProvider(Me.ConnectionProvider)
End Sub
End Class
Public Class ConnectionProvider
Inherits Ninject.Activation.Provider(Of IConnection)
Public Property Connection As IConnection
Protected Overrides Function CreateInstance(ByVal context As Ninject.Activation.IContext) As IConnection
Return Me.Connection
End Function
End Class
Imports Ninject
Module EntryPoint
Sub Main()
Dim provider As New ConnectionProvider
Dim standardModule As New StandardModule
Dim connection As IConnection
Dim kernel As New Ninject.StandardKernel()
standardModule.ConnectionProvider = provider
kernel = New Ninject.StandardKernel(standardModule)
' Here you should use a factory instead of create an instance directly but
' for demonstration, it show how an instance can be propagated to object created
' by NInject.
provider.Connection = New Connection
connection = kernel.Get(Of IConnection)()
End Sub
End Module
This article by Ayende in MSDN Magazine is ostensibly about NHibernate, and mentions the word inject only once (and that only wrt AOP), but the phrasing of your question suggests to me it'll be great food for thought as you consider how to architect your app.
You can also make your frameworks depend on a factory instance, and rely on the factory to perform your connection pooling.
Alternatively, you can use Ninject itself to always use the same object instance for the particular type.