[seasar-dotnet:237] [S2Dao]SelectメソッドのDTO引数か否かの判定について

kubo jazzflute @ mbn.nifty.com
2006年 6月 11日 (日) 00:04:02 JST


久保です。

○環境
WindowsXP SP2
VS2005 Team Edition
.NET 2.0
S2Container.NET 1.2.0-RC2 (.NET 2.0)
S2Dao.NET 0.4.2
{ASP開発}

DaoMetaDataImpl#SetupSelectMethodByAuto(MethodInfo)

における処理に関してです。


このメソッドでは、該当のSelectメソッドが、
- DTO引数を利用するのか?
- それとも引数をそのまま利用するのか?
を判定して、CreateAutoSelectSqlByDto(Type)とCreateAutoSelectSql(string[])
を呼び分ける部分があります。
そこの判定で少しおかしいかと思われる部分があります。

if(argNames.Length == 0 && mi.GetParameters().Length == 1) // ←★
{
    argNames = new string[] { "dto" };
    sql = CreateAutoSelectSqlByDto(argTypes[0]);
}
else
{
    sql = CreateAutoSelectSql(argNames);
}

argNamesが0件でかつメソッドの引数の数が1つの場合に、DTO引数を
利用します。しかし、それら変数の定義を見ると:(以下)

string[] argNames = MethodUtil.GetParameterNames(mi);

これは、内部で mi.GetParameters(); のName属性をstring[]に
詰め替えています。なので、argNames.Lengthとmi.GetParameters().Lengthは
必ず同じ値になるのではないかと思います。
よって、CreateAutoSelectSqlByDto()が呼ばれません。(実際にやってみました)


恐らく、C#だとMethodの変数名を取得できるので、Java版に存在する
ARGS-Annotationを利用する必要がなく、

String[] argNames = annotationReader_.getArgNames(method);

が、↓↓↓

string[] argNames = MethodUtil.GetParameterNames(mi);

という実装になっていると思うのですが、

if(argNames.Length == 0 && mi.GetParameters().Length == 1) // ←

の判定がJava版と同じままになってしまっているのでこの現象が
起きているのかと思います。



Java版では、極端な話ARGS-Annotationの有無で判定をしているような
感じですが、ARGS属性を利用しないC#ではその判定ができません。
なので、ちょっとどのような判定をするのが正解なのかがわかりかねます。

とりあえず現状では、暫定で以下のように修正して対応しています。

if (argNames.Length == 1 && IsDtoTargetArgName(argNames[0])) {
    argNames = new String[] { "dto" };
    sql = CreateAutoSelectSqlByDto(argsTypes[0]);
    // /----------------------------------------------------- [MyExtension]
    if (LdConditionBeanContext.IsTheTypeConditionBean(argsTypes[0])) {
        cmd = NewLdS2DaoSelectDynamicCommand(handler).SetSelectClause(sql);
    }
    // -----------/
    ...

protected virtual bool IsDtoTargetArgName(String name) {
    if (name.Equals("dto") || name.Equals("entity") || name.Equals("cb")) {
        return true;
    } else {
        return false;
    }
}

引数が1個で、引数名がdtoやentityなどであればDTO引数として利用する。

[判定ロジック案]
A. 引数が1個で引数の名前が[dto/entity/...]であればDTO引数
B. 引数が1個で引数の型が[string/int/long/...]でなければDTO引数
C. 引数が1個で引数が「あるInterface」をImplementsしてる場合はDTO引数

など考えられます。

個人的には、Seasar.Dao内に、IDtoArgumentといった感じのInterfaceを
用意して、それをImplementsしてる場合はDTO引数とするのが良いかと
思っています。理由は、判定基準が利用者側にわかりやすいからです。
但し、Stringや既存のClassをDTOとして扱えないのでマズいのかも
しれません。


この辺はJava版の方の仕様とすり合わせる必要があるのかないのか
ちょっとわからないですが、A/B/Cもしくはその他の方法で、
CreateAutoSelectSqlByDtoが実行されるように修正を検討して
頂けませんでしょうか?

(勘違いしてたらごめんなさい)





-- 
kubo <jazzflute @ mbn.nifty.com>




seasar-dotnet メーリングリストの案内