我有ASP.NET MVC3项目,我想使用自定义成员资格提供程序。另外,我想使用Unity来解析我的依赖注入。
这是来自Global.asax的代码:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer();
container.RegisterType<IAuthentification, Authentification>();
container.RegisterType<IRepository, Repository>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
这是来自我的会员提供商的代码:
public class CustomMembershipProvider : MembershipProvider
{
[Dependency]
private IProveaRepository Repository { get; set; }
public override bool ValidateUser(string username, string password)
{
.....
}
问题是当我将断点放到ValidateUser方法时,我看到Repository属性没有初始化。但这种结构:
[Dependency]
private IProveaRepository Repository { get; set; }
例如,在控制器中工作正常。
有人知道为什么会这样,该怎么办?
答案 0 :(得分:17)
过去几天我遇到了同样的问题。我最终得到了以下解决方案(更改了类型和字段名称以匹配您的)。
public class CustomMembershipProvider : MembershipProvider
{
private IProveaRepository repository;
public CustomMembershipProvider()
: this (DependencyResolver.Current.GetService<IProveaRepository>())
{ }
public CustomMembershipProvider(IProveaRepository repository)
{
this.repository= repository;
}
public override bool ValidateUser(string username, string password)
{
...
}
}
因此,即使Unity无法控制CustomMembershipProvider
的构建,无参数构造函数也会通过MVC3 DependencyResolver
调用Unity来提供正确的存储库实例。
如果您正在对CustomMembershipProvider
进行单元测试,那么您可以直接使用Unity构建一个实例,它将使用第二个构造函数并避免调用DependencyResolver
。
答案 1 :(得分:1)
Unity无法将IProveaRepository实例注入您的自定义成员资格提供程序,因为:
如果您在代码中使用了成员资格priovider类,则可以执行以下操作:
尝试将customMembershipProvider包装在抽象中,例如IMembershipProvider,它只对您使用的方法签名。结果是这样的:
public class CustomMembershipProvider : MembershipProvider, IMembershipProvider
然后你可以统一注册:
container.RegisterType<IMembershipProvider, CustomMembershipProvider>(new InjectionProperty(new ResolvedParameter<IProveaRepository>()));
然后约束是在控制器中传递依赖关系:
public class HomeController : Controller
{
private IMembershipProvider _membershipprovider;
public HomeController(IMembershipProvider membershipProvider)
{
_membershipProvider = membershipProvider
}
// some actions
}
但最好不要使用属性注入,而是构造函数注入:
public class CustomMembershipProvider : MembershipProvider
{
private IProveaRepository Repository { get; set; }
public CustomMembershipProvider(IProveaRepository proveaRepository)
{
Repository = proveaRepository
}
public override bool ValidateUser(string username, string password)
{
.....
}
这是我理解它的方式并且会这样做。但也许有更好的方法,或者我忽略了一些有助于实现它的Unity API。
无论如何,我希望它有所帮助。
答案 2 :(得分:0)
虽然其他人说Unity不能在提供商中注入依赖关系,因为他们不知道 对于容器而言,即使可能是供应商的注册,您也没有通过容器构建供应商的“工厂点”,这是一个不违反良好设计原则的解决方案。 (这是因为,即使大多数人忽略了这一点,使用ServiceFactory也太靠近反模式......)
但是,一个好的解决方案可能是将[Dependency]
属性与Unity BuildUp
方法结合使用的关联。
所以以你的榜样为例,得到你想要做的事情,保留所有的东西,并在提供者构造函数中加入 BuildUp 调用
public class CustomMembershipProvider : MembershipProvider
{
[Dependency]
private IProveaRepository Repository { get; set; }
public CustomMembershipProvider()
{
//contextual obtained container reference
unityContainer.BuildUp(this);
.....
}
public override bool ValidateUser(string username, string password)
{
.....
}
我希望它有所帮助。