我正在开发一个MVC项目,其中控制器操作处理资产。不同的控制器以不同的方式接受assetId参数:一些控制器只使用复杂对象int assetId
(包含保存assetId的属性)获取int id
,其他AssetDTO dto
和其他控制器< / p>
我正在编写一个ActionFilter,它被添加到action方法中,并提供了actionParameter名称,我可以在其中获取资产值。
行动方法:
[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
任何方式我都可以使用动力学?还是反思?等。???
答案 0 :(得分:7)
这里动态来救援。你可以将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
}
}
喝彩!
答案 1 :(得分:0)
嗯,是的,你回答了你的问题。一种方法是使用点符号:
//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
和调用GetProperty
时,代码没有空检查。此外,它不会检查TryParse
的成功与否。请在使用时应用这些更正。
也许这段代码可以使用dynamic
编写,但最后dynamic
用法使用反射编译成对象(就像我在这里所做的那样),因此对我没什么大的影响。< / p>
此外,也许更清楚的是有一个像“idObj.SubObj.id”这样的参数,但这又取决于偏好,而且代码将变得有点更复杂。