在 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
}

我怀疑您反对 SaveResultJObject 都是由库定义的 classes(分别为 Breeze.ContextProviderNewtonsoft.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;
}

但是如果 BreezeNewtonsoft.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 中);对我来说很好。