Вызов статического метода интерфейса для экземпляра, который его реализует

Имея объект, который реализует интерфейс со статическим методом, как я могу вызвать этот статический метод?

Обратите внимание, что я не хочу добавлять TRequest к общей подписи, я имитирую IMediatR.

Это ошибка, которую я получаю: CS0176 Member 'IApiRequest<TResponse>.GetRequestPath()' cannot be accessed with an instance reference; qualify it with a type name instead

internal class Program
{
    static void Main(string[] args)
    {
        var request = new GetAdditionalUserClaimsQuery();
        Execute(request);
    }

    public static void Execute<TResponse>(IApiRequest<TResponse> request)
    {
        // How do I call GetRequestPath here?
        string requestPath = ((IApiRequest<TResponse>)request).GetRequestPath();
    }

    public interface IApiRequest<TResponse>
    {
        static abstract string GetRequestPath();
    }

    public class GetAdditionalUserClaimsQuery : IApiRequest<GetAdditionalUserClaimsResponse>
    {
        public static string GetRequestPath() => "accounts/get-additional-user-claims";
    }

    public class GetAdditionalUserClaimsResponse
    {
    }
}

Думайте об этом как об обычном статическом методе. Как вы можете вызвать общедоступный статический метод для экземпляра? Вы не можете... вы должны полностью квалифицировать статический вызов (также известный как GetAdditionalUserClaimsQuery.GetRequestPath();. То же самое применимо и здесь.

David L 21.02.2023 17:53

Вы уверены, что ваш GetRequestPath должен быть static? Для меня это больше похоже на то, что вы вызываете экземпляр request (как вы все равно сейчас пытаетесь), чем на класс

derpirscher 21.02.2023 18:00

Мне нужно вызвать его статически на сервере, чтобы зарегистрировать конечные точки API, и на экземплярах в клиенте, чтобы определить, куда звонить, поэтому мне нужно и то, и другое.

Peter Morris 22.02.2023 10:12
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
1
3
108
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Статические методы не нуждаются в экземпляре, поэтому вы можете передать null. Используя отражение, это работает.

    public static void Execute<TResponse>(IApiRequest<TResponse> request)
    {
        var requestType = request.GetType();
        var method = requestType.GetMethod("GetRequestPath", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
        var result = method?.Invoke(null, new object[] { });
    }

Раньше у меня были проблемы с этим в WASM, но сегодня утром я попробовал, и это сработало. Спасибо!

Peter Morris 22.02.2023 10:11

Вы также можете просто передать null для параметров вместо создания нового пустого массива. (Или Array.Empty<object>(), если вам действительно нужно передать массив.)

Thomas 23.02.2023 10:17

Поскольку несколько типов могут реализовать IApiRequest<TResponse>, вам нужно добавить еще один общий параметр, чтобы ваш метод знал, какой тип реализует IApiRequest<TResponse> для этого вызова;

public static void Execute<TRequest,TResponse>(TRequest request) where TRequest : IApiRequest<TResponse>{
    ... TRequest.GetRequestPath();
}

Обратите внимание, что это позволяет вызывающему абоненту совершить ошибку, например;

public class AnotherType : GetAdditionalUserClaimsQuery{
   public static string GetRequestPath() => ... ;
}
Program.Execute<GetAdditionalUserClaimsQuery, GetAdditionalUserClaimsResponse>(new AnotherType());

Возможно, вы захотите добавить этот дополнительный параметр в свой интерфейс и запечатать свои реализации;

public interface IApiRequest<TRequest, TResponse> where TRequest : IApiRequest<TRequest, TResponse> {}
public sealed class GetAdditionalUserClaimsQuery : IApiRequest<GetAdditionalUserClaimsQuery, GetAdditionalUserClaimsResponse> {}

Я не хочу этого делать, потому что тогда мне придется указывать оба универсальных типа всякий раз, когда я вызываю метод, тогда как в данный момент он может его вывести. Это тот же подход, что и mediatr.

Peter Morris 22.02.2023 09:06

Другие вопросы по теме