在 Breezejs 中使用依赖注入
Using Dependency Injection with Breezejs
我正在构建一个 EntityFramework/WebApi 后端。
我想将我的 WebApi 与 Entity Framework 分离,并利用依赖注入,这样我就可以将 "data source" 换成 Web API。
我一直在研究工作单元和存储库模式。
我也想用breezejs。
breezejs TempHire 示例提供了很多帮助,因此我将以此作为我的问题的示例 -
https://github.com/Breeze/breeze.js.samples/tree/master/net/TempHire
在此示例中,在数据方面我们有 UnitOfWork class -
public class UnitOfWork
{
private readonly EFContextProvider<TempHireDbContext> _contextProvider;
public UnitOfWork()
{
_contextProvider = new EFContextProvider<TempHireDbContext>();
StaffingResources = new Repository<StaffingResource>(_contextProvider.Context);
Addresses = new Repository<Address>(_contextProvider.Context);
// .. etc.
}
public IRepository<StaffingResource> StaffingResources { get; private set; }
public IRepository<Address> Addresses { get; private set; }
// .. etc.
public SaveResult Commit(JObject changeSet)
{
return _contextProvider.SaveChanges(changeSet);
}
}
然后在 WebApi 端,它像这样使用它 -
[BreezeController]
[Authorize]
public class ResourceMgtController : ApiController
{
private readonly UnitOfWork _unitOfWork = new UnitOfWork();
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _unitOfWork.Commit(saveBundle);
}
// ... etc.
}
我想重构成这样的东西,这样我就可以换掉后端。
public class UnitOfWork : IUnitOfWork
public class ResourceMgtController : ApiController
{
private readonly IUnitOfWork _unitOfWork;
public ResourceMgtController(IUnitOfWork unitOfWork) {
this._unitOfWOrk = unitOfWork; // Dependency Injected...
}
// ... etc.
}
我想不通的是如何使它通用。 breeze 客户端需要这样的方法 -
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _unitOfWork.Commit(saveBundle);
}
而且我无法将其放入 IUnitOfWork -
SaveResult SaveChanges(JObject saveBundle)
并真正让它与 breeze 分离,能够将后端换成另一个后端。我是在错误的地方尝试抽象吗?我想如果我想在客户端上使用 breeze,我需要在后端耦合它吗?
您显然可以使用该方法定义接口:
public interface IUnitOfWork {
...
SaveResult SaveChanges(JObject saveBundle); // no problem
}
我怀疑您反对 SaveResult
和 JObject
都是由库定义的 classes(分别为 Breeze.ContextProvider
和 Newtonsoft.Json.Linq
) 你不想在某处引用。
这些引用不会打扰我,就像我介意引用 System.Linq
来获得 IQueryable
一样。事实上,SaveResult
的测试替身(Breeze.ContextProvider
的 public class)非常容易构建。这是它的定义(以及 KeyMapping
的定义,它唯一的非本地依赖类型):
public class SaveResult
{
public List<object> Entities;
public List<KeyMapping> KeyMappings;
public List<object> Errors;
}
public class KeyMapping
{
public string EntityTypeName;
public object TempValue;
public object RealValue;
}
但是如果 Breeze 和 Newtonsoft.Json 引用对你来说是有害的并且你愿意放弃一些类型安全,您始终可以像这样创建界面:
public interface IUnitOfWork {
...
object SaveChanges(object saveBundle); // no safety, no problem
}
然后在你的具体 UnitOfWork
中添加一个合适的重载:
public object IUnitOfWork.SaveChanges(object saveBundle)
{
return SaveChanges((JObject) saveBundle);
}
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
...鲍勃是你的叔叔。
是的,我确实尝试过(在 DocCode 中);对我来说很好。
我正在构建一个 EntityFramework/WebApi 后端。
我想将我的 WebApi 与 Entity Framework 分离,并利用依赖注入,这样我就可以将 "data source" 换成 Web API。
我一直在研究工作单元和存储库模式。
我也想用breezejs。
breezejs TempHire 示例提供了很多帮助,因此我将以此作为我的问题的示例 -
https://github.com/Breeze/breeze.js.samples/tree/master/net/TempHire
在此示例中,在数据方面我们有 UnitOfWork class -
public class UnitOfWork
{
private readonly EFContextProvider<TempHireDbContext> _contextProvider;
public UnitOfWork()
{
_contextProvider = new EFContextProvider<TempHireDbContext>();
StaffingResources = new Repository<StaffingResource>(_contextProvider.Context);
Addresses = new Repository<Address>(_contextProvider.Context);
// .. etc.
}
public IRepository<StaffingResource> StaffingResources { get; private set; }
public IRepository<Address> Addresses { get; private set; }
// .. etc.
public SaveResult Commit(JObject changeSet)
{
return _contextProvider.SaveChanges(changeSet);
}
}
然后在 WebApi 端,它像这样使用它 -
[BreezeController]
[Authorize]
public class ResourceMgtController : ApiController
{
private readonly UnitOfWork _unitOfWork = new UnitOfWork();
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _unitOfWork.Commit(saveBundle);
}
// ... etc.
}
我想重构成这样的东西,这样我就可以换掉后端。
public class UnitOfWork : IUnitOfWork
public class ResourceMgtController : ApiController
{
private readonly IUnitOfWork _unitOfWork;
public ResourceMgtController(IUnitOfWork unitOfWork) {
this._unitOfWOrk = unitOfWork; // Dependency Injected...
}
// ... etc.
}
我想不通的是如何使它通用。 breeze 客户端需要这样的方法 -
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _unitOfWork.Commit(saveBundle);
}
而且我无法将其放入 IUnitOfWork -
SaveResult SaveChanges(JObject saveBundle)
并真正让它与 breeze 分离,能够将后端换成另一个后端。我是在错误的地方尝试抽象吗?我想如果我想在客户端上使用 breeze,我需要在后端耦合它吗?
您显然可以使用该方法定义接口:
public interface IUnitOfWork {
...
SaveResult SaveChanges(JObject saveBundle); // no problem
}
我怀疑您反对 SaveResult
和 JObject
都是由库定义的 classes(分别为 Breeze.ContextProvider
和 Newtonsoft.Json.Linq
) 你不想在某处引用。
这些引用不会打扰我,就像我介意引用 System.Linq
来获得 IQueryable
一样。事实上,SaveResult
的测试替身(Breeze.ContextProvider
的 public class)非常容易构建。这是它的定义(以及 KeyMapping
的定义,它唯一的非本地依赖类型):
public class SaveResult
{
public List<object> Entities;
public List<KeyMapping> KeyMappings;
public List<object> Errors;
}
public class KeyMapping
{
public string EntityTypeName;
public object TempValue;
public object RealValue;
}
但是如果 Breeze 和 Newtonsoft.Json 引用对你来说是有害的并且你愿意放弃一些类型安全,您始终可以像这样创建界面:
public interface IUnitOfWork {
...
object SaveChanges(object saveBundle); // no safety, no problem
}
然后在你的具体 UnitOfWork
中添加一个合适的重载:
public object IUnitOfWork.SaveChanges(object saveBundle)
{
return SaveChanges((JObject) saveBundle);
}
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
...鲍勃是你的叔叔。
是的,我确实尝试过(在 DocCode 中);对我来说很好。