Пожалуйста, не стесняйтесь предложить лучший заголовок для вопроса.Я не могу найти хорошее имя для описания проблемы.
Мне нужно было сделать класс доступным через внедрение зависимостей при запуске.Класс должен быть доступен не только через его конкретную реализацию, но и через интерфейс, который он реализует.И мне нужно убедиться, что это один и тот же экземпляр объекта, возвращаемый обеими инъекциями.
Сценарий реальных миров, который привел меня к одноэлементному случаю, представлял собой нюгет для абстракций, обеспечивающих интерфейс (IStore), несколько нюгетеров, содержащих конкретные реализации.(DBStore, RedisStore).Когда я пытался реализовать проверки работоспособности для каждой реализации магазина, я мог ввести IStore, но не конкретную реализацию.И я хотел использовать некоторые переменные, которые были инициализированы и изменены в конкретной реализации (поэтому мне нужен один и тот же экземпляр для обеих инъекций).Поскольку магазины (надеюсь) используются как синглтоны, это сработало.Я не говорю, что существует реальный сценарий для ограниченного и преходящего пути.Мне просто любопытно, если бы это было возможно, если бы они не были синглетонами.
Следующие коды описывают, как мне удалось сделать это с помощью синглетонов.
Способ, который привел меня к одноэлементному решению:
Имея этот интерфейс:
public interface ITestInterface
{
string ReturnAString();
int ReturnAnInt();
}
и эту конкретную реализацию
public class TestImplementation : ITestInterface
{
private int counter = 0;
public string ReturnAString() {return "a string"; }
public int ReturnAnInt() { return counter++; }
}
Онииспользуется в двух (скажем) сервисах.Один хочет, чтобы интерфейс был внедрен в конструктор, а другому нужна конкретная реализация.
Метод проб и ошибок в методе Startup.ConfigureServices для внедрения одного и того же экземпляра в обоих случаях:
Попробуйте 1:
// only ITestInterface is injected but not TestImplemenation
services.AddSingleton<ITestInterface, TestImplementation>();
Попробуйте 2:
//only TestImplementation is injected (DI does not recognize it implements the Interface)
services.AddSingleton<TestImplementation>();
Попробуйте 3:
// both are injected but they are not singleton any more (counters increment independently)
services.AddSingleton<ITestInterface, TestImplementation>();
services.AddSingleton<TestImplementation, TestImplementation>();
Попробуйте 4:
TestImplementation instance = new TestImplementation();
services.AddSingleton<ITestInterface>(instance);
services.AddSingleton(instance);
//services.AddSingleton<TestImplementation>(instance);
Ну, попробуйте 4У меня один и тот же экземпляр для обеих инъекций.
Теперь давайте предположим, что TestImplementation необходимо ввести некоторые (например, соединения) настройки.
Я могу написать метод расширения для получения настроек из конфигурации и пройтиэто к экземпляру синглтона.
TestImplementation instance = new TestImplementation(Configuration.GetTestSettings());
services.AddSingleton<ITestInterface>(instance);
services.AddSingleton(instance);
Так как же мне добиться, чтобы обе инъекции были одним и тем же экземпляром, используя одни и те же настройки с областью действия или переходным процессом?Так как я не думаю, что смогу создать экземпляр вручную / кодом там.