我有一个名为TopMenuViewModel的ViewModel。它有两个构造器:一个没有参数,一个有应该从Unity推送的参数。
当我想使用视图模型时,注入不起作用,默认的无参数ctor被调用(不是注入的),所以我不能使用依赖项。为什么和如何?:-)
下面是ViewModel:
public class TopMenuViewModel
{
public int unreadMessagesCount { get; set; }
public PersonnelAMEntity personnel { get; set; }
IList<DocumentTypeEntity> quickDocumentTypes { get; set; }
private readonly IPersonnelAMBusiness _IPersonnelAMBusinessRepo;
private readonly IDocumentBusiness _IDocumentBusinessRepo;
private readonly IMessageBusiness _IMessageBusinessRepo;
[InjectionConstructor]
public TopMenuViewModel(IPersonnelAMBusiness personnelRepo, IDocumentBusiness documentRepo, IMessageBusiness messageRepo)
{
_IPersonnelAMBusinessRepo = personnelRepo;
_IDocumentBusinessRepo = documentRepo;
_IMessageBusinessRepo = messageRepo;
}
public TopMenuViewModel() {}
internal void SetMenuFor(int matricule)
{
// Get personnel
this.personnel = _IPersonnelAMBusinessRepo.GetAll(matricule);
// Get message number
unreadMessagesCount = _IMessageBusinessRepo.GetUnreadReceivedMessages(this.personnel).Value.Count;
// Get QuickDocumentTypes
quickDocumentTypes = _IDocumentBusinessRepo.GetAllQuickDocumentTypes(SessionManager.visibilityUnit).Value;
}
}
下面是它的名字:
public ActionResult TopMenu()
{
TopMenuViewModel model = new TopMenuViewModel();
model.SetMenuFor(SessionManager.matricule);
return PartialView("~/Views/Shared/_TopMenu.cshtml", model);
}
当我调用SetMenuFor时,我在_IPersonnelAMBusinessRepo上得到了一个'System.NullReferenceException‘。
下面是UnityConfig (它是由编译器读取的,因为我可以在它上面设置断点(多亏了UnityMvcActivator才能触发):
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager());
container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager());
//container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<AccountController>(new InjectionConstructor(typeof(IPersonnelAMBusiness)));
// Business Layer DI
container.RegisterType<IAMLogBusiness, AMLogBusiness>(); // No dependencies
container.RegisterType<IAuditBusiness, AuditBusiness>(); // No dependencies
container.RegisterType<ICockpitStatBusiness, CockpitStatsBusiness>(); // No dependencies
container.RegisterType<IDistributionListBusiness, DistributionListBusiness>(); // No dependencies
container.RegisterType<IEmailBusiness, EmailBusiness>(); // No dependencies
container.RegisterType<INatureBusiness, NatureBusiness>(); // No dependencies
container.RegisterType<IProfessionBusiness, ProfessionBusiness>(); // No dependencies
container.RegisterType<IReportingBusiness, ReportingBusiness>(); // No dependencies
container.RegisterType<IRequeteBusiness, RequeteBusiness>(); // No dependencies
container.RegisterType<ISocieteBusiness, SocieteBusiness>(); // No dependencies
container.RegisterType<ITopicBusiness, TopicBusiness>(); // No dependencies
container.RegisterType<IUserBusiness, UserBusiness>(); // No dependencies
container.RegisterType<IUnitBusiness, UnitBusiness>(); // No dependencies
container.RegisterType<IDocumentBusiness, DocumentBusiness>(); // No dependencies
container.RegisterType<IInstallationBusiness, InstallationBusiness>(); // Unit(V) dependencies
container.RegisterType<IAnomalyBusiness, AnomalyBusiness>(); // Audit(V), Installation(V) dependencies UNIT
container.RegisterType<IPersonnelAMBusiness, PersonnelAMBusiness>(); // Anomaly(V), profession(V), user(V), audit(V), Unit(V) dependencies
container.RegisterType<IMessageBusiness, MessageBusiness>(); // Personnel(V), Document(V) Unity(V) dependencies
// Set resolver
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
发布于 2018-02-03 08:34:28
当您在控制器操作中使用以下代码时:
TopMenuViewModel model = new TopMenuViewModel();
实际上,您并不是通过Unity Container创建ViewModel实例。您可以使用C# new
运算符调用无参数构造函数来创建它。
要通过Unity创建ViewModel实例,请执行以下操作:
1.将ViewModel的实例注入您的控制器构造函数:
private readonly TopMenuViewModel _viewModel;
public YourController(TopMenuViewModel viewModel)
{
if (viewModel == null)
{
throw new ArgumentNullException(nameof(viewModel));
}
_viewModel = viewModel;
}
请注意,控制器中不应该有其他构造函数。
2.删除TopMenu()
操作中创建的TopMenuViewModel
实例,使用保存在_viewModel
字段中的注入实例:
public ActionResult TopMenu()
{
_viewModel.SetMenuFor(SessionManager.matricule);
return PartialView("~/Views/Shared/_TopMenu.cshtml", _viewModel);
}
3.从TopMenuViewModel
类中删除无参数构造函数。正如NightOwl888
所指出的,在DI中使用多个构造函数是应该避免的反模式。
现在,当Unity MVC接收到请求时,它将通过Unity创建控制器的实例,因为您将UnityDependencyResolver
设置为DependencyResolver
。Unity将解析传递给构造函数的TopMenuViewModel
实例,包括它的所有内部依赖项。
https://stackoverflow.com/questions/48565184
复制