使用封装在接口中的 EF DbContext
,为每个 Web 请求注入依赖项,以确保整个请求处理相同的上下文。还有一个自定义RoleProvider
,它使用DbContext
by 接口来自定义授权服务。
到目前为止,我一直在使用服务定位器模式来解析DbContext
customRoleProvider
的无参数构造函数中的实例。这导致了一些小问题,因为它RoleProvider
是单例的,因此它可能会DbContext
无限期地保留 a 而其他请求可能希望在Application_EndRequest
.
我现在有一个基于此的解决方案,尽管使用了与 windsor 不同的 ioc 容器。我可以使用 DIRoleProvider
为每个 http 请求新建一个自定义实例。
我的问题是,我应该吗?
有一个开放的DbContext
悬挂RoleProvider
似乎很浪费。另一方面,我知道每个 MVC 都会AuthorizeAttribute
命中RoleProvider
(如果它有一个非空Roles
属性,我们大多数人都会这样做),所以我想已经有一个DbContext
等待的可能很有用。
另一种方法是为不是每个 web 请求注入不同DbContext
的。RoleProvider
这样DbContext
,只为 web 请求而存在的 s 可以在最后被处理,而不会影响单例RoleProvider
。
哪种方法更好,为什么?
评论后更新
史蒂文,这基本上就是我所做的。唯一的区别是我不依赖System.Web.Mvc.DependencyResolver
. 相反,我在自己的项目中基本上有相同的东西,只是名称不同:
public interface IInjectDependencies
{
object GetService(Type serviceType);
IEnumerable<object> GetServices(Type serviceType);
}
public class DependencyInjector
{
public static void SetInjector(IInjectDependencies injector)
{
// ...
}
public static IInjectDependencies Current
{
get
{
// ...
}
}
}
这些类是项目核心 API 的一部分,并且与 MVC 位于不同的项目中。这样,其他项目(连同域项目)就不需要依赖System.Web.Mvc
它来编译它的DependencyResolver
.
鉴于该框架,到目前为止,使用 SimpleInjector 替换 Unity 已经很轻松了。下面是多用途单例 RoleProvider 设置的样子:
public class InjectedRoleProvider : RoleProvider
{
private static IInjectDependencies Injector
{ get { return DependencyInjector.Current; } }
private static RoleProvider Provider
{ get { return Injector.GetService<RoleProvider>(); } }
private static T WithProvider<T>(Func<RoleProvider, T> f)
{
return f(Provider);
}
private static void WithProvider(Action<RoleProvider> f)
{
f(Provider);
}
public override string[] GetRolesForUser(string username)
{
return WithProvider(p => p.GetRolesForUser(username));
}
// rest of RoleProvider overrides invoke WithProvider(lambda)
}
网络配置:
<roleManager enabled="true" defaultProvider="InjectedRoleProvider">
<providers>
<clear />
<add name="InjectedRoleProvider" type="MyApp.InjectedRoleProvider" />
</providers>
</roleManager>
IoC 容器:
Container.RegisterPerWebRequest<RoleProvider, CustomRoleProvider>();
至于 CUD,我的中只实现了 1 种方法CustomRoleProvider
:
public override string[] GetRolesForUser(string userName)
这是 MVC AuthorizeAttribute
(and IPrincipal.IsInRole
) 使用的唯一方法,在所有其他方法中,我只是
throw new NotSupportedException("Only GetRolesForUser is implemented.");
由于提供者没有角色 CUD 操作,我不担心交易。