为什么它需要默认构造函数而不是直接使用我的工厂方法?

时间:2017-04-26 11:03:44

标签: c# asp.net-core asp.net-core-mvc

使用 Visual Studio 2017 我有一个 ASP.NET Core MVC应用程序。我注册了工厂的必要方法,因为在模型中,我的每个类的每个实例都只能通过工厂创建:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ITechnicalTask>(_ =>
        // It returns ITechnicalTask instance
        ModelFactory.Current.CreateTechnicalTaskTemplate(
            "Template Name"));

    // Add framework services.
    services.AddMvc();

}

我的控制器有这样的方法:

[HttpGet]
public IActionResult CreateTemplate() => View();

[HttpPost]
public IActionResult CreateTemplate(ITechnicalTask item)
{    
    repo.Templates.Add(item);
    return View("TemplatesList");
}

这是我的表格:

<form asp-action="CreateTemplate" method="post">
    <div class="form-group">
        <label asp-for="TemplateName">Template name:</label>
        <input class="form-control" asp-for="TemplateName" />
    </div>
    <div class="text-center">
        <button class="btn btn-primary" type="submit">
            Accept
        </button>
    </div>
</form>

Accept按钮时出现异常:

  

处理请求时发生未处理的异常。

     

InvalidOperationException:无法创建类型的实例   'PikProject.RobotIRA.ITechnicalTask​​'。模型绑定复杂类型必须   不是抽象或值类型,必须具有无参数   构造

     

Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext   的BindingContext)

为什么它需要默认构造函数?为什么使用我的工厂方法是不够的?

UPD

我的商业模式位于其他项目中。它的所有类都是internal。只有接口和耦合类为public。它还定义工厂接口,用于创建接口的必要实例:

public interface IModelFactory {

    IEmployee CreateEmployee(string name,
        string middleName, string surname,
        string post);

    IAddress CreateAddress(string country, string region,
            string town, string street, string hoseNumber = "",
            string notes = "");

    IApproval CreateApproval(IEmployee employee,
        DateTime? datetime = null);

    IApprovalCollection CreateApprovalCollection();

    IRequirementsCollection CreateRequirementsCollection();

    IRequirement CreateRequirement(RequirementTypes type);

    ITechnicalTask CreateTechnicalTaskTemplate(string name);

    ITechnicalTask CreateTechnicalTaskDocument(
        string templateName);

    ITechnicalTaskCollection CreateTechnicalTaskCollection();

    IRepository CreateRepository();
}

始终可以通过该程序集的ModelFactory.Current属性访问当前工厂。因此,没有可在我的ASP.NET Core MVC项目中访问的类或构造函数。

1 个答案:

答案 0 :(得分:6)

您感到困惑dependency injectionmodel binding。有一个很大的不同。请考虑采取以下措施。

IModelFactory注册为服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IModelFactory>(ModelFactory.Current);

    // Add framework services.
    services.AddMvc();
}

现在在您的控制器中,使用FromServices来获取实例,并使用FromForm从帖子中获取创建模型所需的值:

[HttpPost]
public IActionResult CreateTemplate([FromForm] string name, 
                                    [FromServices] IModelFactory factory)
{
    var item = factory.CreateTechnicalTaskTemplate(name);
    repo.Templates.Add(item);
    return View(nameof(TemplatesList));
}

您的工厂应该被视为一项服务。模型绑定需要POCO,而不是接口。