Использование атрибута вызывающей стороны метода C # Performant - PullRequest
2 голосов
/ 19 апреля 2019

Я пишу клиентскую библиотеку для 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 ]

3 голосов
/ 19 апреля 2019

Вы можете попробовать использовать CallerMemberNameAttribute класс .

Атрибуты "Позволяет получить имя метода или свойства вызывающего метода."

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 голос
/ 19 апреля 2019

Если вы настроены на использование атрибутов, то вам придется использовать отражение так или иначе. Некоторые механизмы отражения работают быстрее, чем другие, но вы все равно должны заплатить штраф за время выполнения. С другой стороны, если вам нужно разделить интересы (а использование атрибутов - это не само собой разумеющееся), вы можете подумать об использовании интерфейсов для разделения этих проблем.

Например:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...