首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将逻辑从控制器操作移动到“服务层”,而不使用ASP.NET MVC中的IoC/DI、ASP.NET和存储库模式。

将逻辑从控制器操作移动到“服务层”,而不使用ASP.NET MVC中的IoC/DI、ASP.NET和存储库模式。
EN

Stack Overflow用户
提问于 2016-06-24 15:45:08
回答 3查看 1.6K关注 0票数 1

最近,我从事一个ASP.NET MVC5项目,我深入研究并在操作方法中编写了我所有的逻辑。在为几个控制器完成这些操作之后,我注意到我一直在复制某些业务规则,并且可以在控制器之间被解除和共享。

据我所读,mvc是一个由实体、视图模型和服务组成的层,后者包含您所有的共享业务逻辑。

现在我尽量保持简单,我不想将实体框架封装在某些UoW/Repo中并使用它,因为在这个应用程序生命周期中,我不太可能停止使用实体框架,我不做单元测试,我也不为紧密耦合而烦恼,所以我不觉得我需要一个IoC容器,但是我读到的所有教程似乎都使用了UoW/Repo中的IoC容器或包dbcontext/ef。

我已经读过,应该只有一个实例(在我所见的教程中是通过IoC容器管理的)每个httprequest的DbContext,这是否可以通过在控制器构造函数中实例化它,然后将该引用传递给控制器中所需的任何服务,然后在请求结束时处理它来实现呢?这是管理dbcontext的正确方法吗?

控制器示例:

代码语言:javascript
运行
复制
public class SupplierController : Controller
{
    private Meerkat3Context context;
    private SupplierService supplierService;
    private ratingService SupplierRatingService;

    public SupplierController()
    {
        // instantiate the dbcontext
        this.context = new Meerkat3Context();

        // pass dbcontext into the constructors of my services
        this.supplierService = New SupplierService(context);
        this.ratingService = New SupplierRatingService(context);
    }
    public ActionResult Index(Guid id)
    {
        var supplier = supplierService.getSupplier(id);
        // construct viewmodel
        return new SupplierIndexViewModel()
        {
            SupplierId = supplier.Id,
            SupplierName = supplier.Name,

            SupplierRating = ratingService.getHighestRating(supplier.Id),
            NearbySuppliers = supplierService.getNearbySuppliers(supplier.Id),
            // etc
        };
    }
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            context.Dispose();
        }
        base.Dispose(disposing);
    }
}

服务实例:

代码语言:javascript
运行
复制
public class SupplierService
{
    private Meerkat3Context context;

    public SupplierService(Meerkat3Context context)
    {
        this.context = context;
    }
    public Supplier getSupplier(Guid id)
    {
        return context.Where(x => x.SupplierId == id)
                      .FirstOrDefault()
                      .Select(x => new Supplier()
                      {
                           Id = x.Id,
                           Name = x.Name
                           // etc
                      });
    }
    public Supplier getNearbySuppliers(Guid id)
    {
        return context.Suppliers.Where(x => context.SupplierAddresses
                                .Where(y => y.AddressTypeId == AddressTypes.Location)
                                .Select(z => z.Address.TownCity)
                                .Contains(x.SupplierAddresses
                                           .Where(y => y.AddressTypeId == AddressTypes.Location)
                                           .FirstOrDefault()
                                           .Address.TownCity)
                                 );
    }
}

public class SupplierRatingService
{
    private Meerkat3Context context;

    public RatingService(Meerkat3Context context)
    {
        this.context = context;
    }
    public SupplierRating getHighestRating(Guid id)
    {
        return context.SupplierRating
                      .Where(x => x.SupplierId == id)
                      .OrderBy(x => x.RatingValue)
                      .FirstOrDefault()
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-24 15:51:47

如果您想要的只是简单地移出可重用逻辑,那么您的方法就足够好了。但请记住:

  1. 它是不可测试的(您不能隔离您的依赖项和
  2. 您仍然在重复逻辑,即使它只是一个对象构造逻辑(例如,在每个需要SupplierService的控制器中,您也必须实例化Meerkat3Context )。这可能会变得非常乏味(而DI正是在这里派上用场)
票数 0
EN

Stack Overflow用户

发布于 2016-06-24 15:57:21

如果您试图删除重复的代码,这应该相当简单。在VS中,您可以高亮显示一段代码并使用热键Ctrl+R,Ctrl+M进行重构,也可以通过使用上下文菜单highlight code section > right-click > Refactor > Extract Method来实现。

如果可以为所有实体复制重复代码的用法,则可以创建包含此公共功能的静态类。

代码语言:javascript
运行
复制
public sealed class Utlities 
{
    public static CommonA() { }
    public static CommonB() { }
    ... etc...
}

您可以使用Utilities.CommonA()轻松地调用它们。另一种减少冗余的方法是使用ViewModels。基本上,创建要作为ViewModel使用的实体的副本,并具有视图所需的其他属性。如果模型有共同的数据,则创建一个基类来继承这些共性。

代码语言:javascript
运行
复制
public class BaseViewModel 
{
    public Type Prop {get; set;}
    public Type Prop2 {get; set;}
    ...etc...
}

public class SpecificViewModel : BaseViewModel
{
    SpecificViewModel(Type Prop, Type Prop2) : base(Prop, Prop2, ...etc...) { }
    public Type specificProp {get; set;}
    ...etc...
}

如果我正确理解了你的问题,那就是。

票数 1
EN

Stack Overflow用户

发布于 2016-06-24 16:24:17

有了一个IoC容器,您的控制器看起来就像。

代码语言:javascript
运行
复制
 public class SupplierController : Controller
    {
        //the controller doesn't need to create the db context now
        //this concern is handled now by the IoC container

        private SupplierService supplierService;
        private RatingService SupplierRatingService;

        public SupplierController(SupplierService supplierService, RatingService ratingService)
        {
            // we don't have to pass the db context now to services, since we retrieve the services from the IoC container. The IoC container auto-wires the services 
            this.supplierService = supplierService;
            this.ratingService = ratingService;
        }
        public ActionResult Index(Guid id)
        {
            var supplier = supplierService.getSupplier(id);
            // construct viewmodel
            return new SupplierIndexViewModel()
            {
                SupplierId = supplier.Id,
                SupplierName = supplier.Name,

                SupplierRating = ratingService.getHighestRating(supplier.Id),
                NearbySuppliers = supplierService.getNearbySuppliers(supplier.Id),
                // etc
            };
        }
        // the controller doesn't need a dispose method since the IoC container will dispose the dbcontext for us
    }

您不必遵循依赖反转原则才能使用IoC容器,但是您可以依靠IoC容器来创建和管理服务对象的生存期。

您可以配置IoC容器,以便为每个web请求创建一个dbcontext实例。更好的是,这是可配置的,如果以后决定每个服务都有不同的dbcontext实例,那么只需在一个地方而不是在使用新关键字的每个控制器和每个操作方法中更改它。

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

https://stackoverflow.com/questions/38017283

复制
相关文章

相似问题

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