2012-11-24 23 views
6

Denetleyici eylemlerinin Varlıklar ile uğraştığı bir MVC projesi üzerinde çalışıyorum. Bazı denetleyiciler basitçe int assetId, diğer int id alabilir ve diğerActionParameters'dan karmaşık bir nesne geri alma

Ben eklenir bir ActionFilter yazıyorum (assetid tutan bir özelliği içeren) bir kompleks nesne AssetDTO dto kullanarak: Farklı kontrolörleri farklı bir şekilde assetid parametresinde almak eylem yöntemi ve varlık değerini alabildiğim actionParameter adıyla sağlanır.

Eylem Yöntemi:

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

nitelik olarak tanımlanır: beklendiği gibi çalışır

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)) 
     { 
        ...... 
     } 
    } 

, fakat sadece assetid ilkel olarak sağlandığında çalışacaktır. AssetId, karmaşık bir nesne içinde eylem yöntemine verildiğinde ne yapacağından emin değilim.

Her bir nesneyi türüne bağlı olarak farklı şekilde ayrıştırmam gerekecek mi? AssetIdFilter öğesinde, varlık öğesinin nerede olduğunu söylemek için bir çeşit nokta gösterimi belirtebileceğimi umuyordum: dto.assetId

Dinamikleri kullanabileceğim herhangi bir yol var mı? ya da yansıma ?? vb. ???

cevap

7

ve burada dinamik olmak actionFilterAttribute değiştirebilir rescue.you gelir:

 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 
      } 
     } 

alkış!

0

Evet, sorunuza cevap verdiniz. Tek yönlü nokta işaretini kullanmak olacaktır: gerçi GetProperty çağrılırken ToString arayarak ve ne zaman

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(); 
    } 
} 

kod boş çekler yok şu şekildedir:

//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 
} 

Ve AssetIdAttribute olduğunu. Ayrıca, TryParse'un başarısını kontrol etmez. Lütfen bu düzeltmeleri kullanıldığında uygulayın.

Belki bu kod dynamic kullanılarak yazılmış olabilir, ancak sonunda dynamic kullanım yansıma (burada yaptıklarını gibi bir şey) bana bu şekilde hiçbir büyük fark kullanarak nesne derlendi.

Ayrıca, belki de "idObj.SubObj.id" gibi bir parametre olması daha net olurdu, ama yine tercihinize bağlıdır ve kod biraz daha karmaşık hale gelecektir.