Asp.net mvc 4 使用接口作为SimpleInjector ASP.NET MVC的控制器操作参数

Asp.net mvc 4 使用接口作为SimpleInjector ASP.NET MVC的控制器操作参数,asp.net-mvc-4,dependency-injection,simple-injector,Asp.net Mvc 4,Dependency Injection,Simple Injector,我将ASP.NET MVC 4与SimpleInjector一起使用,当MVC框架试图解决从视图将对象传递回控制器操作时应创建的具体类型时,遇到了一个问题。这是它唯一不起作用的地方,我收到一个错误[MissingMethodException:无法创建接口实例。] 我知道也有人问过类似的问题,但没有一个能真正解决这个问题。编写自定义ModelBinder的最佳实践是什么?还是我在SimpleInjector上遗漏了什么?我觉得奇怪的是,当其他一切(如构造函数注入)都运行得很好时,这种方法就不起作

我将ASP.NET MVC 4与SimpleInjector一起使用,当MVC框架试图解决从视图将对象传递回控制器操作时应创建的具体类型时,遇到了一个问题。这是它唯一不起作用的地方,我收到一个错误[MissingMethodException:无法创建接口实例。]

我知道也有人问过类似的问题,但没有一个能真正解决这个问题。编写自定义ModelBinder的最佳实践是什么?还是我在SimpleInjector上遗漏了什么?我觉得奇怪的是,当其他一切(如构造函数注入)都运行得很好时,这种方法就不起作用了

视图:

控制器:

public ActionResult Update(IEntityType entityType)
    {
        ... controller code

        return RedirectToAction("Index");
    }
Global.asax

Container container = new SimpleInjector.Container();
container.Register<IEntityType, EntityTypeModel>();
EntityTypeModel定义:

public interface IEntityType
{
    Int32 EntityTypeId { get; set; }
    Guid EntityTypeGUID { get; set; }
    String EntityTypeName { get; set; }
    String EntityTypeDescription { get; set; }
}
public class EntityTypeModel : IEntityType
{
    public Int32 EntityTypeId { get; set; }
    public Guid EntityTypeGUID { get; set; }
    public String EntityTypeName { get; set; }
    public String EntityTypeDescription { get; set; }
}

默认情况下,MVC不能为您建模绑定接口,您通常不应该尝试建模绑定接口。其思想是对简单的数据容器或对象(如视图模型)进行模型绑定。因此,您的问题并非仅限于简单的喷油器;NET的通用DI框架都不允许在默认情况下集成到MVC模型绑定过程中,因为这不是一种建议的方法

因此,通常情况下,您应该在视图和控制器之间发送视图模型对象,或者在非常简单的场景中,您甚至可以只发送实体,但这仅在实体也是简单数据容器时才起作用。若您的实体是简单的数据容器,那个么为每个实体定义一个接口是无用的,因为接口是用来抽象行为的,而不是数据。模拟或伪造只包含数据的类是毫无用处的

如果你在练习,你的实体将有行为,但即使在这种情况下,为实体定义接口也是非常不寻常的,因为实体是你领域的核心,它们不需要模仿、伪造、拦截或修饰。而是将抽象传递到实体的方法中。在实践DDD时,不太可能在MVC中将实体直接用作视图模型,因为在DDD中,您倾向于隐藏实体的不变量,而视图模型只是一个具有get/set属性(或公共字段)的简单数据容器

还请注意,实体是短期对象,而您在DI容器中注册的服务往往是长期对象。换言之,实体是。您不应该在容器中注册新事物。对于实体,通常是您的存储库层或ORM创建实体;不是集装箱

因此,与其尝试添加钩住容器框架的自定义模型绑定器,我的建议是执行以下操作:

  • 抛弃
    IEntityType
    抽象;这是一个无用的抽象概念
  • 删除
    Register()
    注册,因为它注册的是一个新表,而不是容器的作业
  • 模型直接绑定您的
    EntityTypeModel
    ,方法是更改操作方法以接受
    EntityTypeModel
    ,而不是接受接口,或者将其包装在包含公共
    EntityTypeModel模型{get;set;}
    属性的自定义视图模型中

  • 另一种更复杂的方法是在应用程序的核心层定义消息对象,每个对象描述一个用例。您可以使用这些DTO直接映射到MVC视图。当应用程序不仅仅执行CRUD操作时,这种方法非常有用。看一看。

    你的接口和类看起来像什么?为什么你有一个用于该DTO的接口?“你在这里抽象出什么行为?”史蒂文对这个物体说,可能什么都没有,因为它非常简单。当然,我可以把模型改成EntityTypeModel,一切都会好起来的。然而(我决不是一个专家),有些东西不适合我,模型需要是一个具体的对象。我无法预测我的实现在未来会发生怎样的变化,因此为什么接口让我能够灵活地进行更改,而不必更新依赖于模型的视图。把其他地方抽象出来,然后在视图中绑定一个具体的模型,这似乎是错误的。不管怎样,我还是要谢谢你的详细回答,史蒂文!那么如何解决我的问题呢?我的解决方案Web Business(BLL)和Data中有3个项目。在数据中,我有EF实体、存储库、DTO(与实体相同)和返回DTO的映射器。在BLL中,我有DTO和映射器的服务和接口。我的Web项目无法使用DTO,因为它无法看到它们。我的项目中的引用:Web->BLL
    public class EntityTypeModel : IEntityType
    {
        public Int32 EntityTypeId { get; set; }
        public Guid EntityTypeGUID { get; set; }
        public String EntityTypeName { get; set; }
        public String EntityTypeDescription { get; set; }
    }