/// <summary> /// Gets the service entry associated with the given interface and name. /// </summary> /// <param name="self">The target <see cref="IServiceContainer"/>.</param> /// <param name="name">The (optional) name of the entry.</param> /// <param name="mode">Options.</param> /// <returns>The requested service entry.</returns> /// <exception cref="ServiceNotFoundException">If the service could not be found.</exception> public static AbstractServiceEntry?Get <TInterface>(this IServiceContainer self, string?name, QueryModes mode = QueryModes.Default) { if (self == null) { throw new ArgumentNullException(nameof(self)); } return(self.Get(typeof(TInterface), name, mode)); }
/// <summary> /// Gets the service entry associated with the given interface. /// </summary> /// <param name="self">The target <see cref="IServiceContainer"/>.</param> /// <param name="mode">Options.</param> /// <returns>The requested service entry.</returns> /// <exception cref="ServiceNotFoundException">If the service could not be found.</exception> public static AbstractServiceEntry?Get <TInterface>(this IServiceContainer self, QueryModes mode = QueryModes.Default) => self.Get <TInterface>(null, mode);
public virtual AbstractServiceEntry?Get(Type serviceInterface, string?name, QueryModes mode) { CheckNotDisposed(); Ensure.Parameter.IsNotNull(serviceInterface, nameof(serviceInterface)); Ensure.Parameter.IsInterface(serviceInterface, nameof(serviceInterface)); IServiceId key = MakeId(serviceInterface); AbstractServiceEntry existing; using (FLock.AcquireReaderLock()) { // // 1. eset: Vissza tudjuk adni amit kerestunk. // if (FEntries.TryGetValue(key, out existing)) { return(existing); } // // 2. eset: A bejegyzes generikus parjat kell majd feldolgozni. // bool hasGenericEntry = mode.HasFlag(QueryModes.AllowSpecialization) && serviceInterface.IsGenericType && FEntries.TryGetValue ( MakeId(serviceInterface.GetGenericTypeDefinition()), out existing ); // // 3. eset: Egyik se jott be, vagy kivetelt v NULL-t adunk vissza. // if (!hasGenericEntry) { return(!mode.HasFlag(QueryModes.ThrowOnError) ? (AbstractServiceEntry?)null : throw new ServiceNotFoundException(string.Format(Resources.Culture, Resources.SERVICE_NOT_FOUND, key.FriendlyName()))); } } Assert(existing.IsGeneric()); Assert(mode.HasFlag(QueryModes.AllowSpecialization)); using (FLock.AcquireWriterLock()) { // // Kozben vki berakta mar? // if (FEntries.TryGetValue(key, out AbstractServiceEntry? specialized)) { return(specialized); } // // Ha nem mi vagyunk a tulajdonosok akkor ertesitjuk a tulajdonost h tipizalja o a bejegyzest // majd masoljuk az uj elemet sajat magunkhoz (epp ugy mint ha "orokoltuk" vna). // // Igy lehetove tesszuk h pl singleton elettartamnal a tipizalt peldany elettartamarol is a // deklaralo kollekcio gondoskodjon. // if (existing.Owner != this) { specialized = existing .Owner .Get(serviceInterface, name, mode); // // "specialized" lehet NULL ha a "QueryModes.ThrowOnError" nem volt beallitva es "existing" // nem valositja meg a "ISupportsSpecialization" interface-t. // return(specialized?.CopyTo(this)); } // // Ha mi vagyunk a tulajdonosok akkor nekunk kell tipizalni majd felvenni a bejegyzest. // if (existing is ISupportsSpecialization generic) { // // Ne az "FEntries.Add(specialized, specialized)"-ot hivjuk mert a "this.Add()" virtualis. // Add(specialized = generic.Specialize(serviceInterface.GetGenericArguments())); return(specialized); } return(!mode.HasFlag(QueryModes.ThrowOnError) ? (AbstractServiceEntry?)null : throw new NotSupportedException(Resources.ENTRY_CANNOT_BE_SPECIALIZED)); } IServiceId MakeId(Type iface) => new ServiceId(iface, name); }