这不是合理的设计模式。您可以做的是使用依赖注入将业务接口作为注入依赖项传递给您的视图模型(Unity 示例)。然后,注入的业务服务可以向其中注入数据服务接口,在该接口中可以找到数据上下文。
将数据层放在表示层中被认为是不好的做法。这是一个关于如何分离代码层的示例方法。
下面是 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);
}
}
这会被注入到业务服务中,而业务服务又会被注入到我的虚拟机中:
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());
...