Я провожу некоторые эксперименты с обобщенными c типами и изо всех сил пытаюсь достичь того, что ищу. Я на самом деле не уверен, что это возможно. Вот пример:
public class Request { }
public class RequestTest : Request { }
public class Response { }
public class ResponseTest : Response { }
public abstract class Base
{
// some stuff
}
public abstract class WebMethodBase<TInput, TOutput> : Base
where TInput : Request
where TOutput : Response
{
public abstract TOutput Execute();
protected TInput Input { get; set; }
protected TOutput Output { get; set; }
public WebMethodBase(TInput input, TOutput output)
{
Input = input;
Output = output;
}
}
public class Test : WebMethodBase<RequestTest, ResponseTest>
{
public override ResponseTest Execute()
{
// Do some treatment with the input
Console.WriteLine("Test");
return Output;
}
public Test(RequestTest input, ResponseTest output) : base(input, output) { }
}
public static class WebMethodBaseHelper
{
public static WebMethodBase<TInput, TOutput> Create<TInput, TOutput>(TInput input, TOutput output)
where TInput : Request
where TOutput : Response
{
Type baseType = typeof(WebMethodBase<TInput, TOutput>);
Type childType = baseType.Assembly.GetTypes().Where((t) => baseType.IsAssignableFrom(t) && t.IsClass).FirstOrDefault();
var constructor = childType.GetConstructor(new Type[] { typeof(TInput), typeof(TOutput) });
return (WebMethodBase<TInput, TOutput>)constructor.Invoke(new Object[] {input, output});
}
class Program
{
private static TOutput Execute<TInput, TOutput>(TInput input, TOutput output)
where TInput : Request
where TOutput : Response
{
WebMethodBase<TInput, TOutput> webMethod = WebMethodBaseHelper.Create(input, output);
return webMethod.Execute();
}
private static ResponseTest Run(RequestTest request)
{
return Execute(request, new ResponseTest());
}
static void main(string[] args)
{
ResponseTest result = Run(new RequestTest());
}
}
Этот пример работает, но для тех, кто читает этот код, неясно, какая реализация WebMethodBase<>
запускается при вызове метода Execute
. Чего я хотел бы добиться, так это изменить метод Execute
, чтобы он мог вызывать его таким образом внутри метода Run
:
return Execute<Test>(request);
Поскольку класс Test
наследует WebMethodBase<>
Я предполагаю, что каким-то образом мы сможем извлечь обобщенные типы c и сделать целую функцию также обобщенной c, но я не совсем уверен, что это возможно. Я уже пробовал много разных способов, и это самая близкая реализация, которую мне удалось получить из того, что я хочу.
Любая помощь для достижения этого или объяснение того, почему это невозможно, будет высоко ценится.
Спасибо
Редактировать
Я могу получить то, что хочу, имея следующее:
private static TOutput Execute<TMethod, TInput, TOutput>(TInput input)
where TMethod : WebMethodBase<TInput, TOutput>
where TInput : Request
where TOutput : Response, new()
{
TOutput output = new TOutput();
var constructor = typeof(TMethod).GetConstructor(new Type[] { typeof(TInput), typeof(TOutput) });
TMethod instance = (TMethod)constructor.Invoke(new Object[] { input, output });
return instance.Execute();
}
И называя это так:
return Execute<Test, RequestTest, ResponseTest>(request);
Но я не хочу указывать все три типа каждый раз, когда мне нужно вызвать метод Execute
.