[英]Dependency Injection with Ninject in Session_Start method of web form application
[英]Dependency Injection in ASP.net Session_Start method
我正在学习依赖注入并首次使用autofac。 我在几个autofac示例中提到了容器(见下文),并从我的application_start中调用
public class ContainerConfig
{
public static void RegisterContainer()
{
//Create a new ContainerBuilder
var builder = new ContainerBuilder();
// Register all the controllers using the assembly object
builder.RegisterControllers(Assembly.GetExecutingAssembly());
//Registering default convention -- IExample and Example
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.Single(i => i.Name == "I" + t.Name))
.AsImplementedInterfaces();
//Build the container
var container = builder.Build();
//Set the default resolver to use Autofac
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
我使用IUserService在我的Core项目中创建了UserService。 这有使dbcall从表中获取用户信息的方法。 在我的UI项目中,我有一个名为UserProvider的类,我想要注入UserService。
public class UserProvider
{
private readonly IUserService _userService;
public UserProvider(IUserService userService)
{
_userService = userService;
}
public void LoadCurrentUser()
{
Users FoundUser = _userService.ImportOrGetUser();
if (FoundUser != null)
{
//add it to session
CurrentUser = FoundUser;
}
}
}
这个UserProvider,我在session_start中使用
void Session_OnStart()
{
UserProvider OUsrPrv = new UserProvider(new UserService());
OUsrPrv.LoadCurrentUser();
}
在上面的代码中,如果我传递'new UserService()',我的理解是我手动注入UserService。 我不知道autofac如何在这里提供帮助。 谷歌中的所有示例都在讨论MVCController或WebApiController中的依赖注入,而不是像我正在做的那样在个别类(UserProvider)中。
有人可以请点亮一下吗? 我做错了吗?
为了正确使用依赖注入 ,您永远不应该自己创建实例,底层框架应该为您提供实例。
但ASP.net在没有任何依赖注入的情况下调用Session_OnStart
。 在这种情况下,您可以使用DependencyResolver.Current
静态属性来解析所请求的服务。
void Session_OnStart()
{
UserProvider userProvider = DependencyResolver.Current.GetService<UserProvider>();
userProvider.LoadCurrentUser();
}
System.Web.HttpApplication
的事件模型是ASP.NET的一部分,而不是MVC。 它不是为与依赖注入一起使用而设计的。
Cyril建议的答案是使用服务定位器来获取对服务的引用。 这远非理想,因为您在代码中对服务定位器进行依赖。
以MVC为中心的实现横切关注点(例如将用户数据加载到会话状态)的方法是使用全局注册的过滤器。 您可以实现IAuthorizationFilter
或IActionFilter
以获得所需的效果。 在这种情况下,使用IActionFilter
是有意义的,因为您要等到确定在调用之前有授权用户。
注意:虽然这可以回答您的具体问题,但最好不要在MVC中使用此方案的会话状态。 另一种方法是使用ASP.NET Identity with Claims来存储用户配置文件数据,而不是使用Session。
using System;
using System.Web.Mvc;
using System.Security.Principal;
public class GetUserActionFilter : IActionFilter
{
private readonly IUserRepository userRepository;
public GetUserActionFilter(IUserRepository userRepository)
{
if (userRepository == null)
throw new ArgumentNullException("userRepository");
this.userRepository = userRepository;
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// Do nothing - this occurs after the action method has run
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
IPrincipal user = filterContext.HttpContext.User;
if (user == null)
{
return;
}
IIdentity identity = user.Identity;
if (identity == null)
{
return;
}
// Make sure we have a valid identity and it is logged in.
if (identity.IsAuthenticated)
{
string key = "__CurrentUserData";
var userData = filterContext.HttpContext.Session[key];
if (userData == null)
{
// User data doesn't exist in session, so load it
userData = userRepository.GetUserData(identity.Name);
// Add it to session state
filterContext.HttpContext.Session[key] = userData;
}
}
}
}
现在,要全局添加过滤器,您需要:
RegisterGlobalFilters
方法。 使用命名实例将其与其他潜在的IActionFilter
实例区分开来。
builder.RegisterType<GetUserActionFilter>()
.Named<IActionFilter>("getUserActionFilter");
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters, IContainer container)
{
filters.Add(container.ResolveNamed<IActionFilter>("getUserActionFilter"));
filters.Add(new HandleErrorAttribute());
}
}
public class MvcApplication : System.Web.HttpApplication
{
// This method serves as the composition root
// for the project.
protected void Application_Start()
{
// Register Autofac DI
IContainer container = ContainerConfig.RegisterContainer();
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters, container);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
}
public class ContainerConfig
{
public static IContainer RegisterContainer()
{
//Create a new ContainerBuilder
var builder = new ContainerBuilder();
// Register all the controllers using the assembly object
builder.RegisterControllers(Assembly.GetExecutingAssembly());
//Registering default convention -- IExample and Example
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.Single(i => i.Name == "I" + t.Name))
.AsImplementedInterfaces();
// Register our filter
builder.RegisterType<GetUserActionFilter>()
.Named<IActionFilter>("getUserActionFilter");
//Build the container
var container = builder.Build();
//Set the default resolver to use Autofac
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Return the container to our composition root.
return container;
}
}
请注意,我刚刚在这里使用了存储库服务,因为HttpContext
已经通过动作过滤器直接可用,并且这里需要额外的逻辑,因为我们不确定它是否存在于会话状态中,或者是否甚至存在用户查找,所以我们的过滤器除了加载会话状态外还会执行这些检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.