4

我正在使用 ServiceStack 开发一个(希望如此)RESTful API。

我注意到我的大多数服务看起来都一样,例如,GET 方法看起来这样:

        try
        {
            Validate();
            GetData(); 
            return Response();
        }
        catch (Exception)
        {
            //TODO: Log the exception
            throw; //rethrow
        }

假设我有 20 个资源,20 个请求 DTO,所以我或多或少地获得了大约 20 个相同模板的服务......

我试图创建一个通用或抽象的服务,以便我可以创建只实现相关行为的继承服务,但我被卡住了,因为请求 DTO 不是序列化所需的。

有什么办法吗?

编辑:

我正在尝试做的一个例子:

public abstract class MyService<TResponse,TRequest> : Service
{
    protected abstract TResponse InnerGet();
    protected abstract void InnerDelete();
    public TResponse Get(TRequest request)
    {
        //General Code Here.
        TResponse response = InnerGet();
        //General Code Here.
        return response;
    }

    public void Delete(TRequest request)
    {
        //General Code Here.
        InnerDelete();
        //General Code Here.
    }
}

public class AccountService : MyService<Accounts, Account>
{

    protected override Accounts InnerGet()
    {
        throw new NotImplementedException();//Get the data from BL
    }

    protected override void InnerDelete()
    {
        throw new NotImplementedException();
    }
}
4

2 回答 2

4

为了在New API中做到这一点,我们引入了 IServiceRunner 的概念,它将服务的执行与服务的实现分离。

要添加您自己的服务挂钩,您只需从默认实现中覆盖 AppHost 中的默认服务运行程序:

public virtual IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{           
    return new ServiceRunner<TRequest>(this, actionContext); //Cached per Service Action
}

用你自己的:

public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{           
    return new MyServiceRunner<TRequest>(this, actionContext); //Cached per Service Action
}

MyServiceRunner 只是一个实现您感兴趣的自定义钩子的自定义类,例如:

public class MyServiceRunner<T> : ServiceRunner<T> {
    public override void OnBeforeExecute(IRequestContext requestContext, TRequest request) {
      // Called just before any Action is executed
    }

    public override object OnAfterExecute(IRequestContext requestContext, object response) {
      // Called just after any Action is executed, you can modify the response returned here as well
    }

    public override object HandleException(IRequestContext requestContext, TRequest request, Exception ex) {
      // Called whenever an exception is thrown in your Services Action
    }
}

此外,有关更细粒度的错误处理选项,请查看错误处理 wiki 页面

于 2013-01-29T14:05:31.003 回答
0

我的解决方案是添加一个额外的层,我可以在其中处理每个实体的逻辑:

基本逻辑示例:

public interface IEntity
{
    long Id { get; set; }
}

public interface IReadOnlyLogic<Entity> where Entity : class, IEntity
{
    List<Entity> GetAll();
    Entity GetById(long Id);
}
public abstract class ReadOnlyLogic<Entity> : IReadOnlyLogic<Entity> where Entity : class, IEntity, new()
{
    public IDbConnection Db { get; set; }

    #region HOOKS
    protected SqlExpression<Entity> OnGetList(SqlExpression<Entity> query) { return query; }
    protected SqlExpression<Entity> OnGetSingle(SqlExpression<Entity> query) { return OnGetList(query); }
    #endregion

    public List<Entity> GetAll()
    {
        var query = OnGetList(Db.From<Entity>());
        return Db.Select(query);
    }

    public Entity GetById(long id)
    {
        var query = OnGetSingle(Db.From<Entity>())
                .Where(e => e.Id == id);

        var entity = Db.Single(query);

        return entity;
    }
}

然后我们可以使用如下钩子:

public interface IHello : IReadOnlyLogic<Hello> { }

public class HelloLogic : ReadOnlyLogic<Hello>, IHello
{
    protected override SqlExpression<Hello> OnGetList(SqlExpression<Hello> query)
    {
        return query.Where(h => h.Name == "Something");
    }
}

最后我们的服务只调用我们的逻辑:

public class MyServices : Service
{
    IHello helloLogic;

    public object Get()
    {
        return helloLogic.GetAll();
    }
}
于 2019-03-20T14:51:31.997 回答