DI Containers by definition work by using reflection which means runtime metadata. If you want everything to be checked at compile-time, you should not use a DI Container, but instead hand-wire your dependencies. Applying DI by hand is a common practice called Pure DI.
but after can we change to send through sms without stopping application?
You seem to require the application to respond to configuration changes while keeping running. There are common patterns that allow you to achieve this. Typically you want to define that application's component object graph (the chain of classes that contain behavior with their dependencies) once. Although you might create such graph per request, the shape of the graph should not change later on. Instead, you use patterns such as proxy and composite. For instance considering the following interface and implementations:
interface INotificationSender
{
void Send(string message);
}
class MailNotificationSender : INotificationSender { ... }
class SmsNotificationSender : INotificationSender { ... }
We can define a Proxy as follows:
class ConfigBasedNotificationSenderProxy : INotificationSender
{
private readonly INotificationSender mail;
private readonly INotificationSender sms;
public ConfigBasedNotificationSenderProxy(
INotificationSender mail, INotificationSender sms)
{
this.mail = mail;
this.sms = sms;
}
public void Send(string message)
{
bool sendThroughMail = ReadFromConfgWhereToSendTo();
var sender = sendThroughMail ? this.mail : this.sms;
sender.Send(message);
}
}
You can build the following object graph at application startup:
var sender = new ConfigBasedNotificationSenderProxy(
new MailNotificationSender(...)
new SmsNotificationSender(...));
You can wire this with a DI Container as well, or do it by hand (Pure DI). Important point however that I'm trying to make here is, that even if you need to change how the application behaves at runtime, you don't need to rewire your application. You should be able to change the call graph that goes through the application's object graphs by using Proxy implementations.