检索操作签名自定义属性

时间:2014-09-04 22:52:43

标签: c# reflection asp.net-web-api

假设我有一个如下所示的动作方法:

    [return: Safe]
    public IEnumerable<string> Get([Safe] SomeData data)
    {
        return new string[] { "value1", "value2" };
    }

[Safe]属性是我制作的自定义属性。我想创建一个ActionFilter,它可以在参数或返回类型上找到[Safe]属性。我已经在OnActionExecuting覆盖中使用了这个参数,因为我可以像这样访问我的[Safe]属性:

//actionContext is of type HttpActionContext and is a supplied parameter.
foreach (var parm in actionContext.ActionDescriptor.ActionBinding.ParameterBindings)
{
    var safeAtts = parm.Descriptor.GetCustomAttributes<SafeAttribute>().ToArray();
}

但是如何检索放置在返回类型上的[Safe]属性?

采用这种方法可能需要探索一些事情:

ModelMetadataProvider meta = actionContext.GetMetadataProvider();

但如果这确实有效,则不清楚如何使其与ModelMetadataProvider一起使用。

有什么建议吗?

1 个答案:

答案 0 :(得分:4)

首先尝试从ActionDescriptor转换HttpActionContext属性到ReflectedHttpActionDescriptor。 然后使用MethodInfo属性通过其ReturnTypeCustomAttributes属性检索自定义属性。

public override void OnActionExecuting(HttpActionContext actionContext)
{
  ...
  var reflectedActionDescriptor = actionContext.ActionDescriptor as ReflectedHttpActionDescriptor;
  if (reflectedActionDescriptor != null)
  {
    // get the custom attributes applied to the action return value
    var attrs = reflectedActionDescriptor
                  .MethodInfo
                  .ReturnTypeCustomAttributes
                  .GetCustomAttributes(typeof (SafeAttribute), false)
                  .OfType<SafeAttribute>()
                  .ToArray();
  }
  ...
}

更新:已启用跟踪

ActionDescriptor的具体类型似乎取决于Global Web API Services是否包含ITraceWriter的实例(请参阅:Tracing in ASP.NET Web API)。

默认情况下,ActionDescriptor的类型为ReflectedHttpActionDescriptor。但是,当启用跟踪时 - 通过调用config.EnableSystemDiagnosticsTracing() - ActionDescriptor将被包含在HttpActionDescriptorTracer类型中而不是

要解决此问题,我们需要检查ActionDescriptor是否实现了IDecorator<HttpActionDescriptor>界面:

public override void OnActionExecuting(HttpActionContext actionContext)
{
  ...
  ReflectedHttpActionDescriptor reflectedActionDescriptor;

  // Check whether the ActionDescriptor is wrapped in a decorator or not.
  var wrapper = actionContext.ActionDescriptor as IDecorator<HttpActionDescriptor>;
  if (wrapper != null)
  {
    reflectedActionDescriptor = wrapper.Inner as ReflectedHttpActionDescriptor;
  }
  else
  {
    reflectedActionDescriptor = actionContext.ActionDescriptor as ReflectedHttpActionDescriptor;
  }

  if (reflectedActionDescriptor != null)
  {
    // get the custom attributes applied to the action return value
    var attrs = reflectedActionDescriptor
                  .MethodInfo
                  .ReturnTypeCustomAttributes
                  .GetCustomAttributes(typeof (SafeAttribute), false)
                  .OfType<SafeAttribute>()
                  .ToArray();
  }
  ...
}