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

新しい 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 に答える