Я пытаюсь использовать DI для привязки другой реализации моего сетевого класса. Я смог сделать это успешно, используя не универсальную версию класса. Моя реализация выглядит следующим образом:
class MainClass
{
public static void Main(string[] args)
{
IKernel kernel;
// Hardcode here but will be managed by build system.
bool runningInProd = false;
if (runningInProd)
{
kernel = new StandardKernel(new RealNetworkModule());
}
else
{
kernel = new StandardKernel(new FakeNetworkModule());
}
Session session = kernel.Get<Session>();
session.Authenticate();
}
public class RealNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender)).To(typeof(RealRequestSender));
}
}
public class FakeNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender)).To(typeof(FakeRequestSender));
}
}
}
Класс, который использует мой IRequestSender:
public class Session
{
IRequestSender requestSender;
[Inject]
public Session(IRequestSender requestSender)
{
this.requestSender = requestSender;
}
public void Authenticate()
{
Console.WriteLine(requestSender.Send("Hello There"));
}
}
Интерфейс IRequestSender:
public interface IRequestSender
{
string Send(string request);
}
И две разные реализации:
public class RealRequestSender: IRequestSender
{
public string Send(string request)
{
return "RealRequestSender right back at you: " + request;
}
}
public class FakeRequestSender: IRequestSender
{
public string Send(string request)
{
return "FakeRequestSender right back at you: " + request;
}
}
Это очень просто и работает; тем не менее, мне нужно, чтобы мой IRequestSender использовал универсальные типы, а не строку для ввода:
public interface IRequestSender<RequestT, ResponseT> where RequestT: class where ResponseT: class
{
RequestT Send(RequestT request);
}
И подсчет:
public class FakeRequestSender<RequestT, ResponseT> : IRequestSender<RequestT, ResponseT> where RequestT : class where ResponseT : class
{
public RequestT Send(RequestT request)
{
throw new NotImplementedException();
}
}
public class RealRequestSender<RequestT, ResponseT> : IRequestSender<RequestT, ResponseT> where RequestT : class where ResponseT : class
{
public RequestT Send(RequestT request)
{
throw new NotImplementedException();
}
}
Я сталкивался с несколькими примерами, которые касаются этой проблемы, и я пытался основать на них свою реализацию, но потерпел неудачу. Вот две проблемы, с которыми я сталкиваюсь:
1) Связывание: это главная проблема. Вот как выглядит моя привязка на основе решений, которые я видел в Интернете:
public class RealNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender<>)).To(typeof(RealRequestSender<>));
}
}
VSCode выдает мне ошибку:
Program.cs(29,29): Error CS0305: Using the generic type 'IRequestSender<RequestT, ResponseT>' requires 2 type arguments (CS0305) (DI)
На основании этой ошибки и того, что я прочитал в Интернете, мне все еще не ясно, что мне нужно делать здесь.
2) Доступ к IRequestSender: решение этой проблемы может быть ясным, если я знаю, как исправить привязку. В исходной реализации я использовал [Inject], чтобы получить доступ к IRequestSender, который мне нужен в моем классе Sessions. Однако теперь в общей версии, я думаю, я не смогу сделать это. Если бы я использовал RequestSender без DI, он бы выглядел так:
RequestSender <AuthRequest, AuthResponse> requestSender = new RequestSender<AuthRequest, AuthResponse>();
или
RequestSender <UserRequest, UserResponse> requestSender = new RequestSender< UserRequest, UserResponse >();
для любого количества разных типов.
Так что я не уверен, как получить доступ к RequestSender в этом сценарии.