在派生泛型方法覆盖上查找自定义属性的简洁方法(当方法为异步时)
Clean way to find custom attributes on derived generic method override (when method is Async)
场景:
我正在尝试从基础 class 中的方法中检索自定义属性。这些方法是异步的。
我的基础 class 实现了包含默认逻辑的虚拟方法。具体来说,class 包装了一个 EF IRepository 并将其公开为 Web API w/ Get/Post/Delete 方法。 subclassing 这个基础时的标准做法是在方法重写之上为 Auth 添加一个属性,如 [ResourceClaimsAuthorize(ResourceActions.Write, Resources.SomeResource)]。这些属性是我试图找到的。
问题:
1) 因为我在异步方法中,所以 AsyncStateMachine 会做这件事,如果我尝试调用 MethodBase.GetCurrentMethod(),我将收到 "MoveNext()",而不是实际的方法我在。
2) 我尝试使用 type.GetMethod(string methodName) 代替。为了隐含地工作,我将这种方法与成功获取方法名称的 [CallerMemberName] 属性配对。这部分起作用了——但在我们遇到方法重载的那一刻就中断了。如果存在重载,它不知道如何确定您想要的重载。这可以通过传入一个类型数组来匹配我们想要的重载的方法签名来解决——但我真的不想通过在逻辑中包含一个类型数组来混淆我们的代码——我们试图减少锅炉板,这感觉就像前进 1 步,后退 2 步。
3) 我尝试使用 Expression<Action<T>>
的巧妙技巧作为方法选择器。在这种方法中,我的基础 class 调用我的 Auth 逻辑并传入一个 "selects" 我想要的方法的 lambda。喜欢:
apiController => apiController.Post()
然后你可以通过简单地抓取
很容易地从 MethodCallExpression 中抓取方法
expression.Body.Method; // this will be the methodinfo of the method you selected in your lambda
这几乎奏效了——但是 MethodCallExpression 没有选择派生 class 的方法,出于某种原因,表达式的类型是基础 class,而不是派生 [=50= 】 正如我所料。在我的情况下,这导致只能从所选方法的基本 class 版本中找到自定义属性;它仍然不知道该方法的派生、覆盖版本的自定义属性;这就是我需要的。
有没有更好的方法?
理想情况下,我想像往常一样找到我的自定义属性,w/
var methodInfo = MethodBase.GetCurrentMethod();
var attributes = methodInfo.GetCustomAttributes<MyCustomAttribute>();
但是 AyncStateMachine 打破了这种方法。有没有另一种方法可以从异步方法内部做到这一点,这同样简单?如果不是因为方法重载命名冲突,带 [CallerMemberName] 的 GetCurrentMethod(string methodName) 几乎是一个很好的解决方案,如果不是因为它抓住基 class 方法信息,而不是派生的 class 方法信息。
有什么想法吗?谢谢你的时间!
对于寻找与我相同的东西的任何人,我使用@Jacek Gorgon 的建议找到了一个解决方案:MoveNext instead of actual method/task name
这允许我传入实际异步方法的方法信息,而不是异步状态机方法。 Jacek 提到这不是一个好的生产解决方案,因为它对编译器做出了假设,这在未来可能会发生变化。不幸的是,这是我解决问题的最佳方法,而无需诉诸 "no method overloads are allowed in our api controllers"
到目前为止,一切顺利!
场景: 我正在尝试从基础 class 中的方法中检索自定义属性。这些方法是异步的。
我的基础 class 实现了包含默认逻辑的虚拟方法。具体来说,class 包装了一个 EF IRepository 并将其公开为 Web API w/ Get/Post/Delete 方法。 subclassing 这个基础时的标准做法是在方法重写之上为 Auth 添加一个属性,如 [ResourceClaimsAuthorize(ResourceActions.Write, Resources.SomeResource)]。这些属性是我试图找到的。
问题:
1) 因为我在异步方法中,所以 AsyncStateMachine 会做这件事,如果我尝试调用 MethodBase.GetCurrentMethod(),我将收到 "MoveNext()",而不是实际的方法我在。
2) 我尝试使用 type.GetMethod(string methodName) 代替。为了隐含地工作,我将这种方法与成功获取方法名称的 [CallerMemberName] 属性配对。这部分起作用了——但在我们遇到方法重载的那一刻就中断了。如果存在重载,它不知道如何确定您想要的重载。这可以通过传入一个类型数组来匹配我们想要的重载的方法签名来解决——但我真的不想通过在逻辑中包含一个类型数组来混淆我们的代码——我们试图减少锅炉板,这感觉就像前进 1 步,后退 2 步。
3) 我尝试使用 Expression<Action<T>>
的巧妙技巧作为方法选择器。在这种方法中,我的基础 class 调用我的 Auth 逻辑并传入一个 "selects" 我想要的方法的 lambda。喜欢:
apiController => apiController.Post()
然后你可以通过简单地抓取
很容易地从 MethodCallExpression 中抓取方法expression.Body.Method; // this will be the methodinfo of the method you selected in your lambda
这几乎奏效了——但是 MethodCallExpression 没有选择派生 class 的方法,出于某种原因,表达式的类型是基础 class,而不是派生 [=50= 】 正如我所料。在我的情况下,这导致只能从所选方法的基本 class 版本中找到自定义属性;它仍然不知道该方法的派生、覆盖版本的自定义属性;这就是我需要的。
有没有更好的方法? 理想情况下,我想像往常一样找到我的自定义属性,w/
var methodInfo = MethodBase.GetCurrentMethod();
var attributes = methodInfo.GetCustomAttributes<MyCustomAttribute>();
但是 AyncStateMachine 打破了这种方法。有没有另一种方法可以从异步方法内部做到这一点,这同样简单?如果不是因为方法重载命名冲突,带 [CallerMemberName] 的 GetCurrentMethod(string methodName) 几乎是一个很好的解决方案,如果不是因为它抓住基 class 方法信息,而不是派生的 class 方法信息。
有什么想法吗?谢谢你的时间!
对于寻找与我相同的东西的任何人,我使用@Jacek Gorgon 的建议找到了一个解决方案:MoveNext instead of actual method/task name
这允许我传入实际异步方法的方法信息,而不是异步状态机方法。 Jacek 提到这不是一个好的生产解决方案,因为它对编译器做出了假设,这在未来可能会发生变化。不幸的是,这是我解决问题的最佳方法,而无需诉诸 "no method overloads are allowed in our api controllers"
到目前为止,一切顺利!