问题
I created a custom membership provider
public class MyMembership : MembershipProvider
{
private IRepository<User> Repo;
}
I figured out how to inject MyMembership using autofac:
builder.Register(c => Membership.Provider);
However, this doesn't work if I have a constructor that takes an IRepository (it only calls the parameterless constructor.) I tried doing changing from a private field to a public property and calling:
builder.Register(c => Membership.Provider).AutoWireProperties();
The problem is, MembershipProvider doesn't have a Repo property, it's only my class.
For the time being, I've not injected anything, and just created an empty constructor where I simply create a new instance of my Repo. But it makes it harder for testing.
So, is there any way that I can use AutoFac to inject my MyMembership, and have it use the injected Repo?
回答1:
No. It's not possible.
The DependencyResolver
is not used for the providers (roles/membership) etc.
I've made a membership provider which uses DependencyResolver
internally. All you need to do is to implement IAccountRepository
and register it in your container.
http://blog.gauffin.org/2011/09/a-more-structured-membershipprovider/
回答2:
It's an old post, so i'll just post here my solution as I struggle with it a bit myself.
public class AutofacBootstrapperImp : AutofacBootstrapper
In your autofac builder setup include register for your interface
builder.RegisterType<YourRepo>().As<IRepository<User>>().SingleInstance();
public class CustomMembershipProvider : MembershipProvider
Overload init method and use autofac scope to resolve your type
private IRepository<User> Repo;
public override void Initialize(string name, NameValueCollection config)
{
// use autoface scope to resole service
using (var scope = AutofacBootstrapper.Container.BeginLifetimeScope())
{
Repo = scope.Resolve<IRepository<User>>();
}
if (config == null)
throw new ArgumentNullException("config");
// Initialize the abstract base class.
base.Initialize(name, config);
}
回答3:
You should also register the IRepository<User>
. But to do that you need to access your custom provider by its concrete type.
So something like this:
builder.Register( c => Membership.Provider );
builder.Register( c => ((MyMembership) Membership.Provider).Repo );
That could be made nicer (avoiding casts by registering your implementation) as follows, but not sure on how it then fits in with ASP.NET and its management of provider lifecycles:
builder.RegisterType<MyMembership>();
builder.Register( c => c.Resolve<MyMembership>() ).As<MembershipProvider>();
builder.Register( c => c.Resolve<MyMembership>().Repo );
EDIT:
but from a design standpoint, it looks like your MyMembership
class has a dependency on the IRepository<User>
, therefor something like this is probably best:
builder.RegisterType<YourRepositoryImplementation>().As<IRepository<User>>();
builder.RegisterType<MyMembership>();
builder.Register( c => c.Resolve<MyMembership>() ).As<MembershipProvider>();
That way the IRepository will be injected into the MyMembership as needed, but also be available for direct consumption by other components, and they all have the lifetime management handled by Autofac.
回答4:
This scenario is entirely possible. In my Bootstrapper.cs
class, I just inject the properties into the providers as such:
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
var lifetimeScope = DependencyResolver.Current.GetService<ILifetimeScope>();
lifetimeScope.InjectProperties(Membership.Provider);
lifetimeScope.InjectProperties(Roles.Provider);
I also have the following:
builder.Register(context => Membership.Provider).ExternallyOwned();
builder.Register(context => Roles.Provider).ExternallyOwned();
however I'm not entirely sure if it's even necessary. I believe the Register
s are there in case you want to inject the provider into a type.
来源:https://stackoverflow.com/questions/9396541/how-do-i-inject-a-repository-into-a-custom-membershipprovider-using-autofac