首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的无参数ctor用Unity触发?

为什么我的无参数ctor用Unity触发?
EN

Stack Overflow用户
提问于 2018-02-01 22:34:04
回答 1查看 59关注 0票数 0

我有一个名为TopMenuViewModel的ViewModel。它有两个构造器:一个没有参数,一个有应该从Unity推送的参数。

当我想使用视图模型时,注入不起作用,默认的无参数ctor被调用(不是注入的),所以我不能使用依赖项。为什么和如何?:-)

下面是ViewModel:

代码语言:javascript
运行
复制
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;
    }
}

下面是它的名字:

代码语言:javascript
运行
复制
public ActionResult TopMenu()
{
    TopMenuViewModel model = new TopMenuViewModel();
    model.SetMenuFor(SessionManager.matricule);
    return PartialView("~/Views/Shared/_TopMenu.cshtml", model);
}

当我调用SetMenuFor时,我在_IPersonnelAMBusinessRepo上得到了一个'System.NullReferenceException‘。

下面是UnityConfig (它是由编译器读取的,因为我可以在它上面设置断点(多亏了UnityMvcActivator才能触发):

代码语言:javascript
运行
复制
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));

}
EN

回答 1

Stack Overflow用户

发布于 2018-02-03 16:34:28

当您在控制器操作中使用以下代码时:

代码语言:javascript
运行
复制
TopMenuViewModel model = new TopMenuViewModel();

实际上,您并不是通过Unity Container创建ViewModel实例。您可以使用C# new运算符调用无参数构造函数来创建它。

要通过Unity创建ViewModel实例,请执行以下操作:

1.将ViewModel的实例注入您的控制器构造函数:

代码语言:javascript
运行
复制
private readonly TopMenuViewModel _viewModel;

public YourController(TopMenuViewModel viewModel)
{
    if (viewModel == null)
    {
        throw new ArgumentNullException(nameof(viewModel));
    }

    _viewModel = viewModel;
}

请注意,控制器中不应该有其他构造函数。

2.删除TopMenu()操作中创建的TopMenuViewModel实例,使用保存在_viewModel字段中的注入实例:

代码语言:javascript
运行
复制
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实例,包括它的所有内部依赖项。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48565184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档