使用多个WCF服务合同

时间:2017-08-13 12:06:52

标签: c# wcf

我的项目越来越大,直到现在我只有一份服务合同,我应该将端点分成多个服务合同吗?

1 个答案:

答案 0 :(得分:0)

除了marc_s在评论中发布的重要读物外,还有另一个分裂服务的充分理由。

如果你有(比方说)客户服务,订单服务等,你可以创建一个通用的业务逻辑层,并让你的服务通过调用。由于您的服务现在只涉及一个特定实体,因此可以为该实体注入通用的业务层对象。这意味着您可以避免每个服务中的大量样板代码,因为您的公共服务调用(例如CRUD调用)可以由通用业务逻辑层处理。

例如,这是一个简单的通用业务逻辑层......

public class BaseServiceLogic<T> : BaseServiceLogicInterface<T> where T : class, EntityInterface {
  #region Inject

  [Inject]
  public ILog Logger { get; set; }

  [Inject]
  public BaseRepositoryInterface<T> Repository { get; set; }

  #endregion

  public virtual T GetByID(int id) {
    return Repository.GetByID(id);
  }

  public virtual IEnumerable<T> GetAll() {
    return Repository.GetAll();
  }

  public virtual int Update(int userID, T entity) {
    Logger.Debug("Updating entity (" + entity.ID + ") " + entity.Description + ", user ID " + userID);
    bool newItem = (entity.ID == 0);
    T updatedEntity = Repository.Update(entity);
    if (newItem) {
      Logger.Debug("  ID is now " + updatedEntity.ID);
    }
    return updatedEntity.ID;
  }

  public IEnumerable<ParseError> UpdateEntities(int userID, IEnumerable<T> entities) {
    List<ParseError> errors = new List<ParseError>();
    foreach (T entity in entities) {
      try {
        Update(userID, entity);
      }
      catch (Exception ex) {
        errors.Add(new ParseError {
          EntityID = entity.ID,
          Message = "Saving " + typeof(T) + ": " + ex.Message
        });
      }
    }
    return errors;
  }

  public virtual void Delete(int userID, int id) {
    string description = Repository.GetByID(id).Description;
    Logger.Debug("Deleting entity (" + id + ") " + description + ", user ID " + userID);
    Repository.Delete(id);
  }
}

基础资源库看起来像这样......

public class BaseRepository<T> : BaseRepositoryInterface<T> where T : class, EntityInterface {
  private readonly MyEntities _ctx;
  private readonly DbSet<T> _dbSet;
  private readonly ILog _logger;

  public BaseRepository(AkivaLiebermanEntities ctx, ILog logger) {
  _ctx = ctx;
  _dbSet = _ctx.Set<T>();
  _logger = logger;
}

  public T GetByID(int id) {
  return _dbSet.FirstOrDefault(e => e.ID == id);
}

  public IEnumerable<T> GetAll() {
  return _dbSet;
}

  public T Update(T entity) {
    _logger.Debug("Update(" + entity.ID + ") - " + entity.Description);
    T existingEntity = GetByID(entity.ID);
    if (existingEntity == null) {
      return CreateNew(entity);
    }
    try {
      _ctx.Entry(existingEntity).CurrentValues.SetValues(entity);
      _ctx.SaveChanges();
    }
    catch (Exception ex) {
      _logger.Error("Exception: " + ex.MessageStack());
      throw;
    }
    return existingEntity;
  }

  private T CreateNew(T newEntity) {
    _logger.Debug("CreateNew()");
    try {
      _dbSet.Add(newEntity);
      _ctx.SaveChanges();
    }
    catch (Exception ex) {
      _logger.Error("Exception: " + ex.MessageStack());
      throw;
    }
    _logger.Debug("CreateNew() - new entity: " + newEntity.Description);
    return newEntity;
  }

  public virtual void Delete(int id) {
    T entity = _dbSet.FirstOrDefault(e => e.ID == id);
    if (entity != null) {
      _logger.Debug("Delete(" + id + ") - " + entity.Description);
      try {
        _dbSet.Remove(entity);
        _ctx.SaveChanges();
      }
      catch (Exception ex) {
        _logger.Error("Exception: " + ex.MessageStack());
        throw;
      }
    } else {
      _logger.Debug("Delete(" + id + ") - Not found");
    }
  }
}

有了这个,您的服务代码可以只注入基本业务逻辑的实例,并在那里调用方法,从而避免为每种类型编写业务逻辑调用。例如,您可以拥有一个可以注入类似内容的客户服务......

[Inject]
public BaseServiceLogicInterface<Customer> CustomerServiceLogic { get; set; }

然后您的服务可以按如下方式更新客户......

[OperationContract]
public void UpdateCustomer(Customer c) {
  return CustomerServiceLogic.Update(c);
}

请注意您是否需要在此处编写任何特定于实体的代码?如果你想要一个Contact服务,你可以创建一个.svc部分,并且具有与上面类似的代码,同样不需要特定的联系业务逻辑类。

即使您确实需要为更多特定于实体的操作创建特定的业务逻辑类,您仍然可以使用基类免费获得基本操作。

希望这是有道理的。