最近我正在开发一个ASP.NET MVC5项目,我直接进入并在动作方法中写下我的所有逻辑,在为一些控制器执行此操作后,我注意到我一直在复制某些业务规则并且可以在控制器之间被提升和共享。
根据我的阅读,asp.net mvc中的m是一个由实体,视图模型和服务组成的层,后者包含所有共享的业务逻辑
现在我试图让事情变得尽可能简单,我不想在某些UoW / Repo中包装实体框架并按原样使用它,我不太可能停止使用实体框架这个应用程序的生命周期,我不做单元测试,我不是那么紧张耦合,所以我觉得我不需要一个IoC容器,但我读过的所有教程似乎都使用IoC容器或在UoW / Repo中包装dbcontext / ef。
我已经读过每个httprequest应该只有一个实例(在我看过的教程中通过IoC容器管理)的DbContext,这可以通过在控制器构造函数中实例化然后传递来实现引用控制器中所需的任何服务,然后在请求结束时处理它?这是管理dbcontext的正确方法吗?
控制器示例:
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);
}
}
服务示例:
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()
}
}
答案 0 :(得分:1)
如果您想要的只是移出可重复使用的逻辑,那么您的方法就足够了。但请记住:
它不可测试(您无法隔离您的依赖项和
你仍在复制逻辑,即使它只是一个对象构造逻辑(例如,在你需要的每个控制器中SupplierService
你也必须实例化Meerkat3Context
。这可能会变得相当繁琐(这就是DI派上用场的地方)
答案 1 :(得分:1)
如果你试图删除重复的代码,这应该相当简单。在VS中,您可以突出显示一段代码并使用热键Ctrl+R,Ctrl+M
进行重构,或者您可以使用上下文菜单highlight code section > right-click > Refactor > Extract Method
来执行此操作。
如果可以为所有实体复制重复代码的使用,则可以创建一个包含此常用功能的静态类。
public sealed class Utlities
{
public static CommonA() { }
public static CommonB() { }
... etc...
}
您可以使用Utilities.CommonA()
轻松拨打电话。减少冗余的另一种方法是使用ViewModels。基本上创建要用作ViewModel的实体的副本,其中包含View所需的其他属性。如果模型具有共同的数据,则创建一个基类来继承这些共性。
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...
}
如果我理解你的问题是正确的。
答案 2 :(得分:1)
使用IoC容器,您的控制器看起来像。
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实例,那么你只需在一个地方更改它,而不是在每个控制器和使用new关键字的每个操作方法中更改。 / p>