/// <summary> /// Возвращает гарантированно единственный экземпляр класса на уровне данного экземпляра ExtendedProperties и ключа, заданного в параметре propertyName, /// и создаваемый при первом обращении методом, переданным в параметре singletonConstructor. /// Данный метод не является потокобезопасным. Корректность работы метода гарантируется при однопоточном использовании. /// </summary> /// <param name="propertyName">Имя расширенного свойства, в котором хранится одиночный объект.</param> /// <param name="singletonConstructor">Метод, инициализирующий одиночный объект.</param> /// <param name="resetable">При переданном true, позволяет осуществить сброс singleton-свойства.</param> /// <returns></returns> public object GetSingleton(string propertyName, SingletonConstructor singletonConstructor, bool resetable) { if (string.IsNullOrEmpty(propertyName)) { throw new ArgumentNullException("propertyName"); } if (singletonConstructor == null) { throw new ArgumentNullException("singletonConstructor"); } object singleton = null; //если свойство содержится в ExtendedProperties, возвращаем его //иначе - создаем и устанавливаем. if (this.ContainsProperty(propertyName)) { //получаем объект-одиночку singleton = this.GetProperty(propertyName, null); //ругаемся, если он пустой if (singleton == null) { throw new Exception(string.Format("Не задана ссылка на одиночный объект с названием {0}.", propertyName)); } } else { //создаем объект одиночку, если он не задан. singleton = singletonConstructor(this.Holder); //ругаемся, если конструктор объекта вернул пустоту. if (singleton == null) { throw new Exception(string.Format("Конструктор одиночного объекта с названием {0} вернул ссылку на пустой объект.", propertyName)); } //устанавливаем объект-одиночку в коллекцию ExtendedProperteis. this.SetProperty(propertyName, singleton); } return(singleton); }
public void JobHostServiceProvider_SingletonAndScoped() { // Build JobHostServiceProvider var rootServices = new ServiceCollection(); var rootContainer = rootServices.BuildServiceProvider(); IServiceScopeFactory rootScopeFactory = rootContainer.GetRequiredService <IServiceScopeFactory>(); var jobHostServices = new ServiceCollection(); jobHostServices.AddSingleton <SingletonConstructor>(); jobHostServices.AddSingleton <SingletonFactory>(p => new SingletonFactory(p)); jobHostServices.AddScoped <ScopedConstructor>(); jobHostServices.AddScoped <ScopedFactory>(p => new ScopedFactory(p)); IServiceProvider jobHostProvider = new JobHostServiceProvider(jobHostServices, rootContainer, rootScopeFactory); // Resolve some root services SingletonConstructor rootSingletonConstructor = jobHostProvider.GetService <SingletonConstructor>(); SingletonFactory rootSingletonFactory = jobHostProvider.GetService <SingletonFactory>(); ScopedConstructor rootScopedConstructor = jobHostProvider.GetService <ScopedConstructor>(); ScopedFactory rootScopedFactory = jobHostProvider.GetService <ScopedFactory>(); // Resolve some child scope services SingletonConstructor childSingletonConstructor1; SingletonFactory childSingletonFactory1; ScopedConstructor childScopedConstructor1; ScopedFactory childScopedFactory1; using (var scope = jobHostProvider.CreateScope()) { childSingletonConstructor1 = scope.ServiceProvider.GetService <SingletonConstructor>(); childSingletonFactory1 = scope.ServiceProvider.GetService <SingletonFactory>(); childScopedConstructor1 = scope.ServiceProvider.GetService <ScopedConstructor>(); childScopedFactory1 = scope.ServiceProvider.GetService <ScopedFactory>(); } // Do it again SingletonConstructor childSingletonConstructor2; SingletonFactory childSingletonFactory2; ScopedConstructor childScopedConstructor2; ScopedFactory childScopedFactory2; using (var scope = jobHostProvider.CreateScope()) { childSingletonConstructor2 = scope.ServiceProvider.GetService <SingletonConstructor>(); childSingletonFactory2 = scope.ServiceProvider.GetService <SingletonFactory>(); childScopedConstructor2 = scope.ServiceProvider.GetService <ScopedConstructor>(); childScopedFactory2 = scope.ServiceProvider.GetService <ScopedFactory>(); } // Ensure all ServiceProviders for Singletons are the same. Assert.Same(rootSingletonConstructor.ServiceProvider, childSingletonConstructor1.ServiceProvider); Assert.Same(childSingletonConstructor1.ServiceProvider, rootSingletonFactory.ServiceProvider); Assert.Same(rootSingletonFactory.ServiceProvider, childSingletonFactory1.ServiceProvider); // The root ServiceProviders for Scoped should also be the same. Assert.Same(childSingletonFactory1.ServiceProvider, rootScopedConstructor.ServiceProvider); Assert.Same(rootScopedConstructor.ServiceProvider, rootScopedFactory.ServiceProvider); // Root and child should not match for Scoped Assert.NotSame(rootScopedConstructor.ServiceProvider, childScopedConstructor1.ServiceProvider); Assert.NotSame(rootScopedFactory.ServiceProvider, childScopedFactory1.ServiceProvider); // Both Scopes should match Assert.Same(childScopedConstructor1.ServiceProvider, childScopedFactory1.ServiceProvider); Assert.Same(childScopedConstructor2.ServiceProvider, childScopedFactory2.ServiceProvider); // But not between scopes Assert.NotSame(childScopedConstructor1.ServiceProvider, childScopedConstructor2.ServiceProvider); Assert.NotSame(childScopedFactory1.ServiceProvider, childScopedFactory2.ServiceProvider); // Roots and Singletons are not disposed rootSingletonConstructor.DoSomething(); rootSingletonFactory.DoSomething(); rootScopedConstructor.DoSomething(); rootScopedFactory.DoSomething(); childSingletonConstructor1.DoSomething(); childSingletonFactory1.DoSomething(); childSingletonConstructor2.DoSomething(); childSingletonFactory2.DoSomething(); // Child scopes are disposed. Assert.Throws <ContainerException>(() => childScopedConstructor1.DoSomething()); Assert.Throws <ContainerException>(() => childScopedFactory1.DoSomething()); Assert.Throws <ContainerException>(() => childScopedConstructor2.DoSomething()); Assert.Throws <ContainerException>(() => childScopedFactory2.DoSomething()); }
/// <summary> /// Возвращает гарантированно единственный экземпляр класса на уровне данного экземпляра ExtendedProperties и ключа, заданного в параметре propertyName, /// и создаваемый при первом обращении методом, переданным в параметре singletonConstructor. /// Данный метод не является потокобезопасным. Корректность работы метода гарантируется при однопоточном использовании. /// </summary> /// <typeparam name="T">Тип объекта-одиночки.</typeparam> /// <param name="propertyName">Имя расширенного свойства, в котором хранится одиночный объект.</param> /// <param name="singletonConstructor">Метод, инициализирующий одиночный объект.</param> /// <param name="resetable">При переданном true, позволяет осуществить сброс singleton-свойства.</param> /// <returns></returns> public T GetSingleton <T>(string propertyName, SingletonConstructor singletonConstructor, bool resetable) { return((T)this.GetSingleton(propertyName, singletonConstructor, resetable)); }
/// <summary> /// Возвращает гарантированно единственный экземпляр класса на уровне данного экземпляра ExtendedProperties и ключа, заданного в параметре propertyName, /// и создаваемый при первом обращении методом, переданным в параметре singletonConstructor. /// Данный метод не является потокобезопасным. Корректность работы метода гарантируется при однопоточном использовании. /// </summary> /// <typeparam name="T">Тип объекта-одиночки.</typeparam> /// <param name="propertyName">Имя расширенного свойства, в котором хранится одиночный объект.</param> /// <param name="singletonConstructor">Метод, инициализирующий одиночный объект.</param> /// <returns></returns> public T GetSingleton <T>(string propertyName, SingletonConstructor singletonConstructor) { return((T)this.GetSingleton(propertyName, singletonConstructor)); }
/// <summary> /// Возвращает гарантированно единственный экземпляр класса на уровне данного экземпляра ExtendedProperties и ключа, заданного в параметре propertyName, /// и создаваемый при первом обращении методом, переданным в параметре singletonConstructor. /// Данный метод не является потокобезопасным. Корректность работы метода гарантируется при однопоточном использовании. /// </summary> /// <param name="propertyName">Имя расширенного свойства, в котором хранится одиночный объект.</param> /// <param name="singletonConstructor">Метод, инициализирующий одиночный объект.</param> /// <returns></returns> public object GetSingleton(string propertyName, SingletonConstructor singletonConstructor) { return(this.GetSingleton(propertyName, singletonConstructor, false)); }