Частичный вывод обобщенного типа возможен в C #?

Я работаю над переписыванием моего свободного интерфейса для моей библиотеки классов IoC, и когда я реорганизовал некоторый код для обмена некоторыми общими функциями через базовый класс, я наткнулся на загадку.

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

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

Лучше с примером кода, чем приведенное выше описание.

Вот простой и полный пример того, чтоне Работа:

using System;

namespace ConsoleApplication16
{
    public class ParameterizedRegistrationBase { }
    public class ConcreteTypeRegistration : ParameterizedRegistrationBase
    {
        public void SomethingConcrete() { }
    }
    public class DelegateRegistration : ParameterizedRegistrationBase
    {
        public void SomethingDelegated() { }
    }

    public static class Extensions
    {
        public static ParameterizedRegistrationBase Parameter<T>(
            this ParameterizedRegistrationBase p, string name, T value)
        {
            return p;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ConcreteTypeRegistration ct = new ConcreteTypeRegistration();
            ct
                .Parameter<int>("age", 20)
                .SomethingConcrete(); // <-- this is not available

            DelegateRegistration del = new DelegateRegistration();
            del
                .Parameter<int>("age", 20)
                .SomethingDelegated(); // <-- neither is this
        }
    }
}

Если вы скомпилируете это, вы получите:

'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingConcrete' and no extension method 'SomethingConcrete'...
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingDelegated' and no extension method 'SomethingDelegated'...

Что я хочу, это для метода расширения (Parameter<T>) чтобы можно было ссылаться на обоихConcreteTypeRegistration а такжеDelegateRegistrationи в обоих случаях возвращаемый тип должен соответствовать типу, для которого было вызвано расширение.

Проблема заключается в следующем:

Я хотел бы написать:

ct.Parameter<string>("name", "Lasse")
            ^------^
            notice only one generic argument

но и этоParameter<T> возвращает объект того же типа, к которому он был вызван, что означает:

ct.Parameter<string>("name", "Lasse").SomethingConcrete();
^                                     ^-------+-------^
|                                             |
+---------------------------------------------+
   .SomethingConcrete comes from the object in "ct"
   which in this case is of type ConcreteTypeRegistration

Есть ли способ, которым я могу обмануть компилятор, чтобы сделать этот скачок для меня?

Если я добавлю два аргумента универсального типа вParameter Метод, вывод типа заставляет меня либо предоставить оба, либо ни одного, что означает это:

public static TReg Parameter<TReg, T>(
    this TReg p, string name, T value)
    where TReg : ParameterizedRegistrationBase

дает мне это:

Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments

Что так же плохо.

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

Позвольте мне перефразировать это. Есть ли способ изменить классы в первом примере кода выше, чтобы можно было сохранить синтаксис в методе Main без дублирования рассматриваемых методов?

Код должен быть совместим с C # 3.0 и 4.0.

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

Позвольте мне привести пример:

ServiceContainerBuilder.Register<ISomeService>(r => r
    .From(f => f.ConcreteType<FileService>(ct => ct
        .Parameter<Stream>("source", new FileStream(...)))));
                  ^--+---^               ^---+----^
                     |                       |
                     |                       +- has to be a descendant of Stream
                     |
                     +- has to match constructor of FileService

Если я оставлю оба вывода типа, тип параметра будетFileStreamнеStream.

Ответы на вопрос(5)

Ваш ответ на вопрос