我有一个c#aspnet mvc(不是核心)项目,其中,我使用存储库模式和依赖项注入(ninject)。
这是控制器的示例:
data1=df.groupBy('_c0').agg(collect_list('_c1')).show()
print(data1.count())
data1=df.groupBy('_c0').apply(collect_list('_c1')).show()
public class MainController : Controller
{
ISecurityRepository _securityRepo = default(ISecurityRepository);
AppState _appState;
public MainController(ISecurityRepository securityRepo)
{
_securityRepo = securityRepo;
_appState = (AppState)Session["appstate"];
}
public ActionResult Employee(int employeeId)
{
var permissions = _securityRepo.GetEmployeePermissions(
employeeId,
_appState.userId,
_appState.sessionId);
return View(permissions);
}
public ActionResult Leave(int leaveId, int employeeId)
{
var permissions = _securityRepo.GetEmployeeLeavePermissions(
leaveId,
employeeId,
_appState.userId,
_appState.sessionId);
return View(permissions);
}
public ActionResult Holiday(int holidayId, int employeeId)
{
var permissions = _securityRepo.GetEmployeeHolidayPermissions(
holidayId,
employeeId,
_appState.userId,
_appState.sessionId);
return View(permissions);
}
}
被注入,并且运行良好,但是我想要做的就是获得ISecurityRepository
类的值SecurityRepository
,而无需传递给每个方法{每次{1}}和_appState
。
这是我的userId
companyId
我想做的是拥有这样的东西:
SecurityRepository.cs
注入是在public class SecurityRepository : ISecurityRepository
{
public EmployeePermissions GetEmployeePermissions(int employeeId, int userId, int sessionId)
{
// ... some code here
return employeePermissions;
}
public EmployeeLeavePermissions GetEmployeeLeavePermissions(int leaveId, int employeeId, int userId, int sessionId)
{
// ... some code here
return employeeLeavePermissions;
}
public EmployeeHolidayPermissions GetEmployeeHolidayPermissions(int holidayId, int employeeId, int userId, int sessionId)
{
// ... some code here
return employeeHolidayPermissions;
}
// ... some more methods
}
类内部完成的
public class SecurityRepository : ISecurityRepository
{
// here have maybe a constructor that receives the AppState variable from MainController, or a public property
public EmployeePermissions GetEmployeePermissions(int employeeId)
{
// a way that I can user _appState here!!
return employeePermissions;
}
}
我可以遵循的任何建议或示例代码吗?
答案 0 :(得分:0)
因此,您只需要以某种方式将会话中的值传递给存储库即可。其实有很多方法可以达到这个目的。
一种方法是在存储库类中(当然,在存储库接口中)某种Initialize
方法:
public class SecurityRepository : ISecurityRepository
{
public void Initialize(AppState appState)
{
_userId = appState.userId;
_sessionId = appState.sessionId;
}
// some other methods
}
然后您可以在控制器构造函数中调用它:
public MainController(ISecurityRepository securityRepo)
{
_securityRepo = securityRepo;
_securityRepo.Initialize(Session["appstate"] as AppState);
}
另一种方法-您可以处理在action filter中设置依赖项的问题。只需添加某种访问器即可:
public class AppStateAccessor
{
public AppState AppState { get; set; }
}
然后将其设置在您的过滤器中:
public class RequestScopeDependencySetupFilter : ActionFilterAttribute
{
private readonly IKernel _kernel;
public RequestScopeDependencySetupFilter(IKernel kernel)
{
_kernel = kernel;
}
public override void OnActionExecuted(ActionExecutedContext context)
{
var accessor = _kernel.Get<AppStateAccessor>();
accessor.AppState = context.HttpContext.Session["appstate"] as AppState;
}
}
然后将该过滤器注册为全局过滤器:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
var kernel = /* get your IKernel somehow */
filters.Add(new RequestScopeDependencySetupFilter(kernel));
}
最后在您的存储库中使用它:
public class SecurityRepository : ISecurityRepository
{
public SecurityRepository(AppStateAccessor accessor)
{
_userId = accessor.AppState.userId;
_sessionId = accessor.AppState.sessionId;
}
// some other methods
}
请不要忘记正确绑定您的依赖项。此方法的关键点是您的AppStateAccessor
实例是临时的,并且位于请求范围中。 Ninject(具体为Ninject.Extensions.ContextPreservation
扩展名)使您可以为请求范围绑定DI容器中的对象实例:
private static void RegisterServices(IKernel kernel)
{
// bind AppStateAccessor in request scope
kernel.Bind<AppStateAccessor>().ToSelf().InRequestScope();
// transient repository
kernel.Bind<ISecurityRepository>().To<Data.SecurityRepository>();
// other dependencies...
}
还有另一种方法。只需在您的存储库中使用HttpContext.Current
静态属性:
public class SecurityRepository : ISecurityRepository
{
public SecurityRepository()
{
var appState = HttpContext.Current.Session["appstate"] as AppState;
_userId = appState.userId;
_sessionId = appState.sessionId;
}
// some other methods
}
易于实现,但向存储库添加了静态静态依赖-无需进行单元测试。
还有一种类似于this answer的方式(感谢@Nkosi,它是第二和第三的组合)。从AppStateAccessor
中提取界面:
public interface IAppStateAccessor
{
AppState AppState { get; }
}
然后稍微更改AppStateAccessor
:
public class AppStateAccessor
{
public AppState AppState { get; }
= HttpContext.Current.Session["appstate"] as AppState;
}
然后在您的存储库中使用此界面:
public class SecurityRepository : ISecurityRepository
{
public SecurityRepository(IAppStateAccessor accessor)
{
_userId = accessor.AppState.userId;
_sessionId = accessor.AppState.sessionId;
}
// some other methods
}
这次,您的服务已与HttpContext
完全分离,并且可以轻松进行单元测试。