Компилятор С# не разрешает параметры универсального типа по ограничениям [дубликаты]

У меня есть следующий вариант использования:

Я создал структуру универсальной конечной точки в своем проекте ASP.NET Core WebAPi.

И теперь я хочу написать метод расширения для ServiceCollection, чтобы легко зарегистрировать мои Endpoint в DI.

Сейчас я постараюсь продемонстрировать то, что я хочу. Допустим, у нас есть:

interface IEndPoint<TInput, TOutput>
{
    TOutput Execute(TInput input);
}

class StrToIntEndPoint : IEndPoint<string, int>
{
    public int Execute(string input)
    {
        return int.Parse(input);
    }
}

class ServiceCollection { }

static class ServiceCollectionServiceExtensions
{
    public static void AddScoped<TService, TImplementation>(this ServiceCollection services) where TImplementation : TService
    {

    }
}

static class MyCustomExt
{
    // Here, I have to add TInput, TOutput type parameters to AddEndpoint method too.
    public static void AddEndpoint<T, TInput, TOutput>(this ServiceCollection services) where T: IEndPoint<TInput, TOutput>
    {
        services.AddScoped<IEndPoint<TInput, TOutput>, T>();
    }
}

class Program
{
    static void Main()
    {
        var services = new ServiceCollection();

        // Compile Error: Incorrect number of type parameters
        services.AddEndpoint<StrToIntEndPoint>();

        // fine
        services.AddEndpoint<StrToIntEndPoint, string, int>();

    }
}

Мой вопрос: почему компилятор не разрешает string и int как параметры типа для AddEndpoint, ссылаясь на StrToIntEndPoint?


person Sanan Fataliyev    schedule 24.05.2019    source источник
comment
Это называется частичным выводом, и .Net его не поддерживает, это вопрос все или ничего. Однако, в зависимости от того, как далеко вы хотите зайти в эту кроличью нору и сколько типовой безопасности вы хотите потерять, есть хаки, которые вы можете использовать. может сделать, однако ни один из них не удовлетворяет   -  person TheGeneral    schedule 25.05.2019
comment
Арг. потерять = потерять   -  person TheGeneral    schedule 25.05.2019
comment
@TheGeneral спасибо за термин, я не знал, поэтому я написал код)   -  person Sanan Fataliyev    schedule 25.05.2019


Ответы (2)


К сожалению, общие ограничения/аргументы работают не так. Вы либо указываете НЕТ аргументов универсального типа, и компилятор выводит все аргументы, либо вы указываете их все.

person Jeff    schedule 24.05.2019

Я закончил со следующим решением для моего случая:

static class MyCustomExt
{
    public static IServiceCollection AddScopedWitInterfaces<T>(this IServiceCollection services)
    {
        Type type = typeof(T);

        Type[] interfaces = type.GetInterfaces();

        foreach (Type interfaceType in interfaces)
        {
            services.AddScoped(interfaceType, type);
        }

        return services;
    }
}

И зарегистрируйте мой сервис в ConfigureServices:

services.AddScopedWitInterfaces<StrToIntEndpoint>();
person Sanan Fataliyev    schedule 24.05.2019