C# 使用依赖项注入创建接口实例
我有一个基本控制器,在每次加载页面之前,我都希望获得当前用户。我最初在我的C# 使用依赖项注入创建接口实例,c#,dependency-injection,asp.net-mvc-5,C#,Dependency Injection,Asp.net Mvc 5,我有一个基本控制器,在每次加载页面之前,我都希望获得当前用户。我最初在我的BaseController中有一个构造函数,看起来像这样 public BaseController(ISystemUserCommand command) { _systemUserCommand = command } 这样做的问题是,从BaseController继承的每个控制器都必须在其构造函数中包含ISystemUserCommand,我认为这不好 相反,我尝试只创建服务类的一个实例(如下所示-它是v
BaseController
中有一个构造函数,看起来像这样
public BaseController(ISystemUserCommand command)
{
_systemUserCommand = command
}
这样做的问题是,从BaseController
继承的每个控制器都必须在其构造函数中包含ISystemUserCommand
,我认为这不好
相反,我尝试只创建服务类的一个实例(如下所示-它是var sid下的注释行…),但我需要传入用户服务。我如何在这里传递用户服务,或者这是一种不好的方式
public abstract class BaseController : Controller
{
public SystemUserViewModel CurrentUser { get; set; }
private readonly ISystemUserCommand _systemUserCommand;
public SystemUserViewModel GetCurrentUser()
{
if (HttpContext == null || HttpContext.User == null) return null;
if (CurrentUser != null) return CurrentUser;
var sid = System.Web.HttpContext.Current.Request.LogonUserIdentity.User.ToString();
//var command = new SystemUserCommand();
CurrentUser = _systemUserCommand.GetUser(sid);
return CurrentUser;
}
public void SetUserInformation(SystemUserViewModel currentUser)
{
ViewBag.UserId = currentUser.SystemUserId;
ViewBag.FullName = string.Format("{0} {1}", currentUser.FirstName, currentUser.LastName);
ViewBag.FirstName = currentUser.FirstName;
ViewBag.LastName = currentUser.LastName;
ViewBag.CurrentUser = currentUser;
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var currentUser = GetCurrentUser();
if (currentUser != null)
{
if (currentUser.IsActive)
{
SetUserInformation(currentUser);
}
else
filterContext.Result = RedirectToAction("denied", "unauthorized");
}
else
filterContext.Result = RedirectToAction("denied", "unauthorized");
base.OnActionExecuting(filterContext);
}
}
public class SystemUserCommand : ISystemUserCommand
{
private readonly ISystemUserBusiness _systemUserBusiness;
public SystemUserCommand(ISystemUserBusiness systemUserBusiness)
{
_systemUserBusiness = systemUserBusiness;
}
...
}
您可以通过基类使用属性注入而不是构造函数注入,例如使用unity:
public abstract class BaseController : Controller
{
[Dependency]
public ISystemUserCommand SystemUserCommand { get; set; }
}
这意味着接口引用仅在基类上
有关完整示例,请参见
编辑,自动传真示例:
依赖项上不需要属性属性
public abstract class BaseController : Controller
{
public ISystemUserCommand SystemUserCommand { get; set; }
}
只需在autofac builder上注册要自动解析的属性:
builder.RegisterControllers(typeof(MvcApplication).Assembly).Where(t => t.IsAssignableFrom(typeof(BaseController))).PropertiesAutowired();
请参阅autofac属性注入。您可以通过基类使用属性注入而不是构造函数注入,例如使用unity:
public abstract class BaseController : Controller
{
[Dependency]
public ISystemUserCommand SystemUserCommand { get; set; }
}
这意味着接口引用仅在基类上
有关完整示例,请参见
编辑,自动传真示例:
依赖项上不需要属性属性
public abstract class BaseController : Controller
{
public ISystemUserCommand SystemUserCommand { get; set; }
}
只需在autofac builder上注册要自动解析的属性:
builder.RegisterControllers(typeof(MvcApplication).Assembly).Where(t => t.IsAssignableFrom(typeof(BaseController))).PropertiesAutowired();
请参阅autofac属性注入。首先,在控制器中执行
操作
覆盖似乎不是一个好主意。您可以使用专门为此目的设计的过滤器。这似乎是创建BaseController
的主要原因
关于在所有必需的服务中注入系统命令的问题,我会这样做,但不会从基类继承,因为我通常更喜欢聚合而不是继承。这意味着需要使用该服务的每个控制器都将获得该服务
我曾多次使用的另一个抽象某些操作的选项是创建一个UserSerivce
,它将向控制器提供所需的操作。它将在内部注入ISystemUserCommand
和HttpContext,以便所有控制器都不必执行此任务。您可以使用HttpContext.Current作为静态的,也可以在需要可测试性时将其抽象掉
此外,我不推荐属性注入,因为它比构造函数注入更模糊,如果可能的话,应该首选构造函数注入
您可以阅读有关过滤器的更多信息。不幸的是,如果您使用过滤器,那么注入过滤器本身并不是那么容易,而且大部分都是通过属性注入或ServiceLocator模式来完成的(这通常并不好)。不过,使用一定量的伏都教可能会做得更好。我认为SimpleInjector有很多关于如何在MVC中将DI应用于过滤器的示例和教程,也许他们现在甚至有一个nuget包来实现这一点。首先,在控制器中使用
OnActionExecuting
覆盖似乎不是一个好主意。您可以使用专门为此目的设计的过滤器。这似乎是创建BaseController
的主要原因
关于在所有必需的服务中注入系统命令的问题,我会这样做,但不会从基类继承,因为我通常更喜欢聚合而不是继承。这意味着需要使用该服务的每个控制器都将获得该服务
我曾多次使用的另一个抽象某些操作的选项是创建一个UserSerivce
,它将向控制器提供所需的操作。它将在内部注入ISystemUserCommand
和HttpContext,以便所有控制器都不必执行此任务。您可以使用HttpContext.Current作为静态的,也可以在需要可测试性时将其抽象掉
此外,我不推荐属性注入,因为它比构造函数注入更模糊,如果可能的话,应该首选构造函数注入
您可以阅读有关过滤器的更多信息。不幸的是,如果您使用过滤器,那么注入过滤器本身并不是那么容易,而且大部分都是通过属性注入或ServiceLocator模式来完成的(这通常并不好)。不过,使用一定量的伏都教可能会做得更好。我认为SimpleInjector有很多关于如何在MVC中将DI应用于过滤器的示例和教程,也许他们现在甚至有一个nuget包来验证这一点。你有AutoFac的示例吗?我添加了一个AutoFac示例:)这是否仍然允许构造函数注入,还是所有内容都默认为属性注入?我添加了一种方法来定义自动属性注入的范围,并添加了一个指向AutoFac dos的链接。你有AutoFac的示例吗添加了一个autofac示例:)这是否仍然允许构造函数注入,还是所有内容都默认为属性注入?我添加了一种方法来确定自动属性注入的范围,并添加了一个指向autofac dos的链接。我的基本控制器也做了其他事情,我只是没有包括它。我把
OnActionExecuting
放在这里,因为我想用用户信息填充布局页面的viewbags。你认为我应该使用一个过滤器吗?如果你在你的页面上显示一些常见的数据(比如用户信息),我宁愿创建一个特殊的局部视图,在MVC页面中重用。这是一个非常不明显的操作,其他人可能会认为它看起来“神奇”,直到他们理解它是如何工作的。嗯,好的。因此,如果我在页面的导航栏中输入某人的姓名和公司,我会将其移动到部分视图,然后创建一个过滤器来填充部分视图?不,不完全是这样。您可以将导航栏放在部分视图中,并将命令/服务注入负责该视图的控制器中。那你就把你的爸爸