I am creating WPF application that consumes multiple gRPC CRUD services. Normally, I would create a GrpcChannel instance and populate gRPC Clients using this channel, pass them to DI container for further use in ViewModels.
But the thing is that my WPF application have some sort of "Start Window" where user must provide server credentials (ip and port) to connect to. This fact leads to the problem that I can't instantiate GrpcChannel with gRPC clients and pass them to DI container before application actually starts. I should somehow create GrpcChannel after user passed server credentials and reuse this channel for all gRPC clients.
So, the question is how to properly manage situation when channel should be created at runtime with user credentials?
CodePudding user response:
How about these options?
Option 1 - check for null credentials before calling gRPC (this is what I do)
public interface IGrpcCredentials
{
string? GetIP();
int? GetPort();
}
Usage
public void TryCallGrpcService(){
IGrpcCredentials credentials; //pretend this has been passed here from somewhere
var ip = credentials.GetIP();
if(ip is null){
return;
}
var port = credentials.GetPort();
if(port is null){
return;
}
CallGrpcService((string)ip, (int)port);
}
Option 2 - Initialize the DI with a placeholder service
You might initialize the DI with a placeholder service that wouldn't provide credentials. For example:
public interface IGrpcCredentials
{
bool AreCredentialsAvailable();
string GetIP();
int GetPort();
}
public class RealGrpcCredentials
{
private readonly string _ip;
private readonly int _port;
public RealGrpcCredentials(string ip, int port)
{
_ip = ip;
_port = port;
}
bool AreCredentialsAvailable() => true;
string GetIP() => _ip;
int GetPort() => _port;
}
public class PlaceholderGrpcCredentials
{
bool AreCredentialsAvailable() => false;
string GetIP() => return string.Empty;
int GetPort() => return -1;
}
Usage
// register palceholder before knowing the credentials
container.Register<IGrpcCredentials, PlaceholderGrpcCredentials>();
//ask user for their crednetials
var credentials = ShowUserCredentialsDialog();
//register the actual credentials
container.Register<IGrpcCredentials, RealGrpcCredentials>(new RealGrpcCredentials(credentials.Ip, credentials.Port));
Option 3 - Initialize the DI after the user enters their credentials
Wait before for the user to fill their credentials before initializing the DI container. You'd have to create a start window that doesn't depend on DI and can be launched before DI container gets constructed.