Esempio n. 1
0
        public void IServiceContainer_Add_ShouldDisposeAbstractEntryOnOverride()
        {
            var entry = new AbstractServiceEntry(typeof(IInterface_1), null, Container);

            Container.Add(entry);
            Container.Add(new InstanceServiceEntry(typeof(IInterface_1), null, new Implementation_1_No_Dep(), false, Container));

            Assert.That(entry.Disposed);
        }
Esempio n. 2
0
        public void Container_Instance_ShouldNotBeAServiceOrFactory()
        {
            Container.Instance <IInterface_1>(new Implementation_1_No_Dep());

            AbstractServiceEntry entry = Container.Get <IInterface_1>(QueryModes.ThrowOnError);

            Assert.That(entry.IsInstance());
            Assert.False(entry.IsService());
            Assert.False(entry.IsFactory());
        }
Esempio n. 3
0
        public void IServiceContainer_Contains_ShouldSearchByGetHashCode(string name)
        {
            AbstractServiceEntry
                    entry1 = new AbstractServiceEntry(typeof(IDisposable), name, Container),
                    entry2 = new AbstractServiceEntry(typeof(IDisposable), name, Container);

            Container.Add(entry1);

            Assert.That(Container.Contains(entry1));
            Assert.That(Container.Contains(entry2));
        }
Esempio n. 4
0
        public void Container_Service_ShouldHandleGenericTypes(Lifetime lifetime)
        {
            Container
            .Service(typeof(IInterface_3 <>), typeof(Implementation_3_IInterface_1_Dependant <>), lifetime);

            AbstractServiceEntry entry = Container.Get <IInterface_3 <int> >(QueryModes.AllowSpecialization);

            Assert.That(entry, Is.Not.Null);
            Assert.That(entry.Interface, Is.EqualTo(typeof(IInterface_3 <int>)));
            Assert.That(entry.Implementation, Is.EqualTo(typeof(Implementation_3_IInterface_1_Dependant <int>)));
        }
        private static void ApplyProxy(this AbstractServiceEntry entry, Func <IInjector, Type, object, object> decorator)
        {
            ISupportsProxying setter = (ISupportsProxying)entry;

            //
            // Bovitjuk a hivasi lancot a decorator-al.
            //

            Func <IInjector, Type, object> oldFactory = setter.Factory !;

            setter.Factory = (injector, type) => decorator(injector, type, oldFactory(injector, type));
        }
Esempio n. 6
0
        public void Equals_ShouldDoWhatItsNameSuggests()
        {
            var dummyContainer = new Mock <IServiceContainer>(MockBehavior.Strict).Object;

            using (var entry = new AbstractServiceEntry(typeof(IDisposable), null, dummyContainer))
            {
                Assert.That(entry.Equals(entry));
                Assert.That(entry.Equals(new AbstractServiceEntry(typeof(IDisposable), null, dummyContainer)));
                Assert.That(entry.Equals(null), Is.False);
                Assert.That(entry.Equals(new AbstractServiceEntry(typeof(IDisposable), "cica", dummyContainer)), Is.False);
                Assert.That(entry.Equals(new AbstractServiceEntry(typeof(IDisposable), null, new Mock <IServiceContainer>(MockBehavior.Strict).Object)), Is.False);
            }
        }
Esempio n. 7
0
        public void OwnedServiceInstantiationStrategy_ShouldUseTheExistingInjector()
        {
            using (IServiceContainer container = new ServiceContainer())
            {
                container.Service <IService, Service>(Lifetime.Transient);

                IInjector injector = container.CreateInjector();

                injector.Get <IService>();

                AbstractServiceEntry entry = injector.UnderlyingContainer.Get <IService>();

                Assert.That(entry.Instances.Single().RelatedInjector, Is.EqualTo(injector));
                Assert.That(entry.Instances.Single().RelatedInjector.UnderlyingContainer, Is.EqualTo(entry.Owner));
            }
        }
Esempio n. 8
0
        public void NotOwnedServiceInstantiationStrategy_ShouldInstantiateWithANewInjector()
        {
            using (IServiceContainer container = new ServiceContainer())
            {
                container.Service <IService, Service>(Lifetime.Singleton);

                IInjector injector = container.CreateInjector();

                injector.Get <IService>();

                AbstractServiceEntry entry = injector.UnderlyingContainer.Get <IService>();

                Assert.That(entry.Instances.Single().RelatedInjector, Is.Not.EqualTo(injector));
                Assert.That(entry.Instances.Single().RelatedInjector.UnderlyingContainer.Parent, Is.EqualTo(entry.Owner));
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation). The easiest way to decorate an instance is using the <see cref="InterfaceInterceptor{TInterface}"/> class.
        /// </summary>
        /// <param name="self">The target <see cref="IServiceContainer"/>.</param>
        /// <param name="iface">The interface to be intercepted.</param>
        /// <param name="name">The (optional) name of the service.</param>
        /// <param name="interceptor">The interceptor class.</param>
        /// <returns>The container itself.</returns>
        /// <remarks>You can't create proxies against instances or not owned entries. A service can be decorated multiple times.</remarks>
        /// <exception cref="InvalidOperationException">When proxying is not allowed (see remarks).</exception>
        public static IServiceContainer Proxy(this IServiceContainer self, Type iface, string? name, Type interceptor)
        {
            //
            // A tobbit a ProxyGenerator<> ellenorzi
            //

            if (self == null)
                throw new ArgumentNullException(nameof(self));

            if (interceptor == null)
                throw new ArgumentNullException(nameof(interceptor));

            AbstractServiceEntry entry = self.Get(iface, name, QueryModes.AllowSpecialization | QueryModes.ThrowOnError)!;

            if (entry.Owner != self)
                throw new InvalidOperationException(Resources.INAPROPRIATE_OWNERSHIP);

            entry.ApplyInterceptor(interceptor);

            return self;
        }
Esempio n. 10
0
        /// <summary>
        /// See <see cref="IServiceContainer.Add"/>.
        /// </summary>
        public virtual void Add(AbstractServiceEntry entry)
        {
            CheckNotDisposed();
            Ensure.Parameter.IsNotNull(entry, nameof(entry));

            using (FLock.AcquireWriterLock())
            {
                if (FEntries.TryGetValue(entry, out AbstractServiceEntry existing))
                {
                    //
                    // Abstract bejegyzest felul lehet irni (de csak azt).
                    //

                    if (existing.GetType() != typeof(AbstractServiceEntry))
                    {
                        throw new ServiceAlreadyRegisteredException(string.Format(Resources.Culture, Resources.ALREADY_REGISTERED, existing.FriendlyName()));
                    }

                    if (ShouldDispose(existing))
                    {
                        //
                        // "AbstractServiceEntry"-nel nincs tenyleges Dispose() logika csak azert van hivva
                        // h ne legyen figyelmeztetes a debug kimeneten -> DisposeAsync() hivasnak se lenne
                        // ertelme.
                        //

                        existing.Dispose();
                    }
                }

                //
                // Ha volt mar bejegyzes adott kulccsal akkor felulijra kulomben hozzaadja.
                //

                FEntries[entry] = entry;
            }
        }
Esempio n. 11
0
        public void Aspects_ShouldBeControlledByAspectKind([Values(AspectKind.Service, AspectKind.Factory)] AspectKind kind, [ValueSource(nameof(Lifetimes))] Lifetime lifetime)
        {
            Container.Factory <IMyService>(i => new MyService(), lifetime);

            AbstractServiceEntry entry = Container.Get <IMyService>();

            var mockAspect = new Mock <AspectWithoutImplementation>(MockBehavior.Strict, kind);

            Func <IInjector, Type, object, object>[] delegates = null;

            switch (kind)
            {
            case AspectKind.Service:
                mockAspect
                .Setup(aspect => aspect.GetInterceptorType(It.Is <Type>(t => t == typeof(IMyService))))
                .Returns(typeof(InterfaceInterceptor <IMyService>));

                Assert.DoesNotThrowAsync(async() => delegates = await Internals.ServiceEntryExtensions.GenerateProxyDelegates(typeof(IMyService), new[] { mockAspect.Object }));

                mockAspect.Verify(aspect => aspect.GetInterceptorType(It.Is <Type>(t => t == typeof(IMyService))), Times.Once);
                Assert.That(delegates.Length, Is.EqualTo(1));

                break;

            case AspectKind.Factory:
                var decorated = new MyService();
                mockAspect
                .Setup(aspect => aspect.GetInterceptor(It.IsAny <IInjector>(), It.Is <Type>(t => t == typeof(IMyService)), It.IsAny <IMyService>()))
                .Returns(decorated);

                Assert.DoesNotThrowAsync(async() => delegates = await Internals.ServiceEntryExtensions.GenerateProxyDelegates(typeof(IMyService), new[] { mockAspect.Object }));
                Assert.That(delegates.Single(), Is.EqualTo((Func <IInjector, Type, object, object>)mockAspect.Object.GetInterceptor));

                break;
            }
        }
Esempio n. 12
0
 public static bool IsGeneric(this AbstractServiceEntry entry) => entry.Interface.IsGenericTypeDefinition;
Esempio n. 13
0
        private IServiceReference Resolve(AbstractServiceEntry requested)
        {
            //
            // 1. eset: Csak egy peldanyt kell letrehozni amit vki korabban mar megtett [HasFlag(Built)],
            //          visszaadjuk azt.
            //

            if (requested.State.HasFlag(ServiceEntryStates.Built))
            {
                return(requested.Instances.Single());
            }

            //
            // 2. eset: Uj peldanyt kell letrehozni de nem mi vagyunk a bejegyzes tulajdonosai (megosztott bejegyzes)
            //          ezert letre kell hozni egy dedikalt injector-t.
            //          Megjegyzesek:
            //            - A nem birtokolt bejegyzesek injector peldanyok kozt ertelmezettek ezert minden muveletnek exkluzivnak kell
            //              lennie.
            //            - A Monitor.IsEntered() vizsgalat azert kell h lassuk ha az aktualis szal korabban mar elkezdte feldolgozni a
            //              szerviz igenylest (nem mellesleg a lock(...) rekurzio eseten nem blokkolodna, igy ez a megoldas jol kezeli
            //              azt az esetet is ha kontener altal kezelt elettartamu bejegyzes hivatkozik sajat magara -> nem lesz S.O.E.).
            //

            if (requested.IsShared && !Monitor.IsEntered(requested))
            {
                //
                // ServiceEntry-t zaroljuk h a lock injectorok kozt is ertelmezve legyen.
                //

                lock (requested)
                {
                    //
                    // A lock miatt lehet h kozben vki mar beallitotta.
                    //

                    if (requested.State.HasFlag(ServiceEntryStates.Built))
                    {
                        return(requested.Instances.Single());
                    }

                    //
                    // Letrehozunk egy dedikalt injector-t aminek a felszabaditasa "requested.Owner" feladata lesz
                    //   -> Elettartama meg fog egyezni a bejegyzes elettartamaval (container controlled lifetime)
                    //   -> Ennek az injector peldanynak a felszabaditasa nem befolyasolja a szerviz elettartamat.
                    //

                    Injector dedicatedInjector = CreateScope(requested.Owner, FOptions);

                    try
                    {
                        //
                        // Ugrunk a 3. esetre
                        //

                        return(dedicatedInjector.Resolve(requested));
                    }
                    catch
                    {
                        dedicatedInjector.Dispose();
                        throw;
                    }
                }
            }

            //
            // 3. eset: Uj peldanyt kell letrehozni es ezt az injector peldany ezt megteheti
            //

            Assert(UnderlyingContainer == requested.Owner || UnderlyingContainer.Parent == requested.Owner, "Foreign entry");

            //
            // A result.Value itt meg ures, a SetInstance() allitja be
            //

            IServiceReference result = new ServiceReference(requested, this);

            try
            {
                //
                // Az epp letrehozas alatt levo szerviz kerul az ut legvegere igy a fuggosegei
                // feloldasakor o lesz a szulo (FGraph.Requestor).
                //

                using (FPath.With(result))
                {
                    FPath.CheckNotCircular();

                    result.SetInstance();
                    return(result);
                }
            }
            catch
            {
                result.Release();
                throw;
            }
        }
Esempio n. 14
0
        private IServiceReference Resolve(Type iface, string?name)
        {
            //
            // Ha vkinek a fuggosege vagyunk akkor a fuggo szerviz itt meg nem lehet legyartva.
            //

            Assert(FPath.Requestor?.Value is null, "Already produced services can not request dependencies");

            try
            {
                //
                // Bejegyzes lekerdezese, generikus bejegyzes tipizalasat megengedjuk. A "QueryModes.ThrowOnError"
                // miatt "relatedEntry" tuti nem NULL.
                //

                AbstractServiceEntry requested = Get(iface, name, QueryModes.AllowSpecialization | QueryModes.ThrowOnError) !;

                if (Config.Value.Injector.StrictDI)
                {
                    AbstractServiceEntry?requestor = FPath.Requestor?.RelatedServiceEntry;

                    //
                    // - Ha a fuggosegi fa gyokerenel vagyunk akkor a metodus nem ertelmezett.
                    // - A kerelmezett szerviznek legalabb addig kell leteznie mint a kerelmezo szerviznek.
                    //

                    if (requestor is not null && requested.Lifetime !.CompareTo(requestor.Lifetime !) < 0)
                    {
                        var ex = new RequestNotAllowedException(Resources.STRICT_DI);
                        ex.Data["requestor"] = requestor;
                        ex.Data["requested"] = requested;

                        throw ex;
                    }
                }

                //
                // Fuggosegek feloldasa es peldanyositas (ez a metodus rekurzivan ismet meghivasra kerulhet)
                //

                IServiceReference resolved = Resolve(requested);

                //
                // Minden fuggoseget megtalaltunk, a szerviz sikeresen peldanyositasra kerult.
                // Ha a szervizt egy masik szerviz fuggosege akkor felvesszuk annak fuggosegi listajaba.
                //

                FPath.Requestor?.AddDependency(resolved);
                return(resolved);
            }

            //
            // Ha a rekurzio alatt a Get() nem talal egy fuggoseget akkor vissza adjuk a teljes fuggosegi utat (FPath mar
            // tartalmazhat elemeket epp ezert az utvonalat csak a hivasi sor legvegen kell megadni -> Data[path] == null).
            //

            catch (ServiceNotFoundException e) when(e.Data["path"] is null)
            {
                e.Data["path"] = ServicePath.Format
                                 (
                    FPath
                    .Select(svc => (IServiceId)svc.RelatedServiceEntry)
                    .Append(new ServiceId(iface, name))
                                 );
                throw;
            }
        }
Esempio n. 15
0
 private bool ShouldDispose(AbstractServiceEntry entry) => entry.Owner == this;