7

私は、コントローラーアクションがアセットを処理するMVCプロジェクトに取り組んでいます。さまざまなコントローラーがさまざまな方法でassetIdパラメーターを受け取ります。一部のコントローラーは、単純にint assetId、その他int id、およびその他を複雑なオブジェクトAssetDTO dto(assetIdを保持するプロパティを含む)を使用して取得します。

アクションメソッドに追加され、アセット値を取得できるactionParameter名が指定されたActionFilterを作成しています。

アクション方法:

    [AssetIdFilter("assetId")]
    public ActionResult Index(int assetId)
    {
            ...
    }

属性は次のように定義されます。

public class AssetIdFilterAttribute : ActionFilterAttribute
{
    public string _assetIdParameterKey { get; set; }

    public AssetIdFilterAttribute (string assetIdParameterKey)
    {
        _assetIdParameterKey = assetIdParameterKey;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        int assetId;
        if (Int32.TryParse(filterContext.ActionParameters[_assetIdParameterKey].ToString(), out assetId))
        {
                    ......
        }
    }

これは期待どおりに機能しますが、assetIdがプリミティブとして提供されている場合にのみ機能します。複雑なオブジェクト内でassetIdがactionメソッドに提供された場合の対処方法がわかりません。

タイプに応じて各オブジェクトを異なる方法で解析する必要がありますか?AssetIdFilterである種のドット表記を指定して、assetIdがどこにあるかを示すことができることを望んでいます:dto.assetId

ダイナミクスを使用する方法はありますか?または反射?? ect。???

4

2 に答える 2

8

そしてここでダイナミックが救助に来ます。actionFilterAttributeを次のように変更できます:

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            dynamic assetIdHolder = filterContext.ActionParameters[_assetIdParameterKey];
            if (assetIdHolder.GetType().IsPrimitive)
            {
                //do whatever with assetIdHolder              
            }
            else
            {
                //do whatever with assetIdHolder.assetId
            }
        }

乾杯!

于 2012-11-24T06:10:19.533 に答える
0

ええ、はい、あなたはあなたの質問に答えました。1つの方法は、ドット表記を使用することです。

//simple case:
[AssetId("id")]
public ActionResult Index(string id) {
    //code here
}

//complex case:
[AssetId("idObj", AssetIdProperty = "SubObj.id")]
public ActionResult index(IdObject idObj) {
    //code here
}

そしてAssetIdAttribute、次のとおりです。

public class AssetIdAttribute : ActionFilterAttribute
{
    public string _assetIdParameterKey { get; set; }

    public string AssetIdProperty { get; set; }

    public AssetIdFilterAttribute(string assetIdParameterKey)
    {
        _assetIdParameterKey = assetIdParameterKey;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        int assetId;
        var param = filterContext.ActionParameters[_assetIdParameterKey];
        int.TryParse(GetPropertyValue(param, this.AssetIdProperty).ToString(), out assetId);
        //you code continues here.
    }

    private static string GetPropertyValue(object souce, string property)
    {
        var propNames = string.IsNullOrWhiteSpace(property) || !property.Contains('.') ? new string[] { } : property.Split('.');
        var result = souce;
        foreach (var prop in propNames)
        {
            result = result.GetType().GetProperty(prop).GetValue(result);
        }
        return result.ToString();
    }
}

ToStringただし、呼び出し時および呼び出し時のコードにはnullチェックがありませんGetProperty。また、の成功はチェックされませんTryParse。使用時にこれらの修正を適用してください。

このコードはを使用して記述できるかもしれませんdynamicが、最終dynamic的にはリフレクション(ここで行ったことのようなもの)を使用してオブジェクトにコンパイルされるため、大きな違いはありません。

また、「idObj.SubObj.id」のようなパラメーターを使用する方が明確な場合もありますが、これも設定によって異なり、コードは少し複雑になります。

于 2012-11-30T18:10:48.573 に答える