我尝试使用MVVM模式学习在.NET中构建Web应用程序。我看过一些教程,有一件事我不明白。
每个ViewModel
都包含:
public class IndexModel : PageModel
{
private readonly ApplicationDbContext _dbContext;
public IndexModel(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
..
}
当你有几页(最多10个)时,复制粘贴这个很好,但我的应用程序开始增长,并且使用这种方法开始感觉非常多余。
我无法找到另一篇回答我的问题的帖子,但我想知道是否还有其他方法可以在每个ViewModel上使用_dbContext
而无需使用此冗余?我对设计模式不太熟悉,但是我的启动中的单例模式是一个选项吗?
答案 0 :(得分:2)
添加从PageModel继承的自定义基类。然后从您的自定义基类继承您的所有模型。
public abstract class MyBasePageModel : PageModel
{
protected readonly ApplicationDbContext _dbContext;
public MyBaseModel(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
}
public class IndexModel : MyBasePageModel
{
public IndexModel(ApplicationDbContext dbContext):base(dbContext)
{
//
}
}
答案 1 :(得分:2)
这不是声音设计模式。您可以做的是使用依赖注入(Unity示例)将业务接口作为注入依赖项传递给您的viewmodel。然后,注入的业务服务可以向其中注入一个数据服务接口,在该接口中可以找到数据上下文。
在您的表示层中使用数据层被认为是不好的做法。以下是如何分离代码层的示例方法。
下面是IDataService的简单示例(注意我只处理接口,数据上下文保留在数据服务中):
public class DataService : ServiceBase, IDataService
{
public DataService(IMapper mapper) : base(mapper) { }
public IList<UserDto> GetUsers(bool runSafeMode = true)
{
Func<IList<UserDto>> action = () =>
{
return GetUsers(_ => true);
};
return ExecutorHandler(action, runSafeMode);
}
...
private IList<UserDto> GetUsers(Expression<Func<User, bool>> predicate, bool runSafeMode = true)
{
Func<IList<UserDto>> action = () =>
{
using (var ymse = YMSEntities.Create())
{
var users = ymse.User
.Include(u => u.UserUserProfile)
.Include(m => m.UserUserProfile.Select(uup => uup.UserProfile))
.Include(m => m.UserUserProfile.Select(uup => uup.User))
.Include(m => m.UserUserProfile.Select(uup => uup.UserProfile.UserProfileModule))
.Where(predicate).OrderBy(u => u.UserName).ToList();
return MappingEngine.Map<IList<UserDto>>(users);
}
};
return ExecutorHandler(action, runSafeMode);
}
}
它被注入到业务服务中,而业务服务又注入到我的VM中:
public class DocksViewModel : ViewModelBase
{
public DocksViewModel(IConfigService configService, IEventService eventService, INotificationService notificationService)
{
...
}
}
关注点和一切事物的简单分离是可独立测试的。在这种情况下我的IDataService可以在BaseViewModel中找到,因为我的应用程序是否具有Internet连接,我在sql server和本地json文件之间切换实现以获得数据持久性。以下是使用Unity连接依赖关系的方法,例如:
var unityContainer = new UnityContainer();
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(unityContainer));
unityContainer.RegisterType<IServiceLocator, UnityServiceLocator>(new ContainerControlledLifetimeManager());
// automapper
var config = new MapperConfiguration(cfg =>
cfg.AddProfile(new AutoMapperBootstrap())
);
unityContainer.RegisterType<IMapper>(new InjectionFactory(_ => config.CreateMapper()));
// factories
unityContainer.RegisterType<IWelcomeGateViewFactory, WelcomeGateViewFactory>();
unityContainer.RegisterType<ITrailerPictureViewFactory, TrailerPictureViewFactory>();
// services
unityContainer.RegisterType<IDataService, OfflineDataService>("OfflineDataService", new ContainerControlledLifetimeManager(), new InjectionConstructor(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ServiceLocator.Current.GetInstance<IMapper>()));
unityContainer.RegisterType<IDataService, DataService>(new ContainerControlledLifetimeManager());
unityContainer.RegisterType<ITestDataService, TestDataService>(new ContainerControlledLifetimeManager());
...