C#Performant方法调用方属性用法

时间:2019-04-19 14:08:49

标签: c# reflection attributes

我正在为提供公共和经过身份验证的端点的API编写客户端库。我想轻松地指出哪些端点需要使用属性进行身份验证。例如:

public async Task<ApiResponse> GetPublicData()
{
  var request = CreateRequest( "v1/public" );
  return await _httpClient.GetAsync( request );
}

[RequiresAuthentication]
public async Task<ApiResponse> GetPrivateData()
{
  var request = CreateRequest( "v1/private" );
  return await _httpClient.GetAsync( request );
}

private ApiRequest CreateRequest( string endpoint )
{
   var request = new ApiRequest( endpoint );

   // if (caller has RequiresAuthenticationAttribute)
   //    SignRequest( request, _credentials );

   return request;
}

据我所知,访问CreateRequest的调用者是否具有RequiresAuthenticationAttribute的唯一方法是创建堆栈框架,通过反射找到方法,然后尝试从MethodInfo获取属性。这可能会非常慢。

还有其他方法可以将这些信息传递给被调用者,而这不会影响性能。我知道请求总是会受到API响应时间的限制,但是鉴于它与财务数据有关,因此必须尽快触发请求,并且能够在短时间内完成请求涉及属性而不是手动传递参数的简洁方法会非常好。

2 个答案:

答案 0 :(得分:3)

您可以尝试使用CallerMemberNameAttribute class

属性“允许您获取方法或方法调用者的属性名称。”

private ApiRequest CreateRequest(string endpoint, [CallerMemberName] string callerMemberName= "")
{
    var methodInfo = this.GetType().GetMethod(callerMemberName);
    var attributes = (RequiresAuthenticationAttribute)method.GetCustomAttributes(typeof(RequiresAuthenticationAttribute), true);

    var request = new ApiRequest( endpoint );

    if (attributes.Any())
        SignRequest(request, _credentials);

    return request;
}

答案 1 :(得分:1)

如果您设置使用属性,那么您将不得不以一种或另一种方式使用反射。某些反射机制比其他一些反射机制要快,但是仍然要付出运行时间的代价。另一方面,如果您想要的是关注点分离(并且没有使用属性),那么您可能需要考虑使用接口来分离这些关注点。

例如:

public interface IAuthenticated
{
  public async Task<ApiResponse> GetPrivateData();
}

public interface IPublicAccess
{
  public async Task<ApiResponse> GetPublicData();
}

public async Task<ApiResponse> IPublicAccess.GetPublicData()
{
  var request = CreateRequest( "v1/public" );
  return await _httpClient.GetAsync( request );
}

public async Task<ApiResponse> IAuthenticated.GetPrivateData()
{
  var request = CreateRequest( "v1/private" );
  return await _httpClient.GetAsync( request );
}

private ApiRequest CreateRequest( string endpoint )
{
   var request = new ApiRequest( endpoint );

   // if (caller has RequiresAuthenticationAttribute)
   //    SignRequest( request, _credentials );

   return request;
}