2015-02-23 67 views
0

我正在构建一个EntityFramework/WebApi后端。
我想将我的WebApi从实体框架中解耦出来,并利用依赖注入,以便我可以将Web API的“数据源”换掉。 我一直在寻找工作单元和存储库模式。我也想使用breezejs使用依赖注入与Breezejs

的breezejs TempHire样品已经很多的帮助,所以我将以此作为一个例子,我的问题 -

https://github.com/Breeze/breeze.js.samples/tree/master/net/TempHire

在此示例中,在数据方面,我们拥有的UnitOfWork类 -

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

什么我不能包裹我的头,是我如何使它通用。微风客户需要这样的方法 -

[HttpPost] 
public SaveResult SaveChanges(JObject saveBundle) 
{ 
    return _unitOfWork.Commit(saveBundle); 
} 

我不能把这个IUnitOfWork -

SaveResult SaveChanges(JObject saveBundle) 

而真正保持它的微风分离,能够换出后端的另一个后端。我是否试图在错误的位置抽象?我猜如果我想在客户端轻松一下,我需要在后端连接它。

回答

1

你可以清楚地与该方法定义一个接口:

public interface IUnitOfWork { 
    ... 
    SaveResult SaveChanges(JObject saveBundle); // no problem 
} 

我怀疑你是反对的事实,即SaveResultJObject是图书馆(Breeze.ContextProviderNewtonsoft.Json.Linq分别)定义的类,你宁愿不参考某处。

这些参考资料不会打扰我的任何超过我想引用System.Linq得到IQueryable。事实上,SaveResult(公共类Breeze.ContextProvider)的测试加倍很容易构造。下面是它的定义(和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; 
} 

但如果微风Newtonsoft.Json引用是有害于你,你愿意放弃一些类型安全,你总是可以创建这样的界面:UnitOfWork添加合适的过载

public interface IUnitOfWork { 
    ... 
    object SaveChanges(object saveBundle); // no safety, no problem 
    } 

然后在您的混凝土:

public object IUnitOfWork.SaveChanges(object saveBundle) 
{ 
    return SaveChanges((JObject) saveBundle); 
} 

public SaveResult SaveChanges(JObject saveBundle) 
{ 
    return _contextProvider.SaveChanges(saveBundle); 
} 

...鲍勃是你的叔叔。

是的,我尝试过(在DocCode中);为我工作得很好。

+0

感谢病房。你的解决方案就是我最终做的!您完全阅读我的文章 - 我反对说我在我的通用界面中添加微风特定的代码 - ,特别是不得不添加一个方法来返回元数据,我没有提到。如果我想将它换成直接无缓存的WebApi/EF解决方案,savechanges可能看起来更像这样 - public void SaveChanges(){\t _ctx.SaveChanges(); }和元数据将无关紧要。所以我想无论数据存储如何,我的UnitOfWork界面都需要轻松兼容。 – user210757 2015-02-24 23:40:18