From 5e507979404e3fc81e40f683fb11e1625174f1ef Mon Sep 17 00:00:00 2001 From: Glauco Knihs Date: Wed, 27 Dec 2017 23:26:42 -0200 Subject: [PATCH] Implementation --- src/Aggregate.cs | 74 ++++ src/Aggregates.cs | 26 ++ src/Configuration.cs | 319 ++++++------------ src/ConstructorSelectorPolicy.cs | 173 ++++++++++ src/HierarchicalTransientLifetimeManager.cs | 35 ++ src/MDIExtension.cs | 16 + src/ServiceDescriptorExtensions.cs | 43 +++ src/ServiceProvider.cs | 59 +++- src/ServiceScope.cs | 38 ++- src/ServiceScopeFactory.cs | 32 +- src/TransientObjectPool.cs | 31 ++ ...Unity.Microsoft.DependencyInjection.csproj | 16 +- tests/UnityDependencyInjectionTests.cs | 8 + 13 files changed, 612 insertions(+), 258 deletions(-) create mode 100644 src/Aggregate.cs create mode 100644 src/Aggregates.cs create mode 100644 src/ConstructorSelectorPolicy.cs create mode 100644 src/HierarchicalTransientLifetimeManager.cs create mode 100644 src/MDIExtension.cs create mode 100644 src/ServiceDescriptorExtensions.cs create mode 100644 src/TransientObjectPool.cs diff --git a/src/Aggregate.cs b/src/Aggregate.cs new file mode 100644 index 0000000..9551c9e --- /dev/null +++ b/src/Aggregate.cs @@ -0,0 +1,74 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using Unity; +using Unity.Injection; +using Unity.Lifetime; + +namespace Unity.Microsoft.DependencyInjection +{ + public class Aggregate + { + public Type Type { get; private set; } + + private List Services { get; set; } = new List(); + private ServiceDescriptor Last; + private IUnityContainer Container; + + public Aggregate(Type type, IUnityContainer container) + { + Type = type; + Container = container; + } + + public void AddService(ServiceDescriptor service) + { + Services.Add(service); + Last = service; + } + + public void Register() + { + foreach (var serv in Services) + { + var qualifier = serv.GetImplementationType().FullName; + Container.Register(serv, qualifier); + } + + Container.RegisterType(Type, Last.GetLifetime(Container), + new InjectionFactory((c, t, s) => + { + if (Last.ServiceType.IsGenericTypeDefinition) + return c.Resolve(t, Last.GetImplementationType().FullName); + var instance = Resolve(c); + return instance; + })); + + var enumType = typeof(IEnumerable<>).MakeGenericType(Type); + Container.RegisterType(enumType, new HierarchicalTransientLifetimeManager(Container), + new InjectionFactory(c => + { + List instances = new List(); + foreach (var serv in Services) + { + if (!serv.ServiceType.IsGenericTypeDefinition) + { + var qualifier = serv.GetImplementationType().FullName; + var instance = Container.Resolve(serv.ServiceType, qualifier); + instances.Add(instance); + } + } + return typeof(Enumerable) + .GetMethod("Cast") + .MakeGenericMethod(Type) + .Invoke(null, new[] { instances }); + })); + } + + public object Resolve(IUnityContainer container) + { + return container.Resolve(Type, Last.GetImplementationType().FullName); + } + } +} diff --git a/src/Aggregates.cs b/src/Aggregates.cs new file mode 100644 index 0000000..7e69dc7 --- /dev/null +++ b/src/Aggregates.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Unity.Microsoft.DependencyInjection +{ + public class Aggregates + { + public List Types { get; set; } + + public Aggregates(List types) + { + Types = types; + } + + public Aggregate Get(Type t) + { + return Types.Where(a => a.Type == t).FirstOrDefault(); + } + + public void Register() + { + Types.ForEach(t => t.Register()); + } + } +} diff --git a/src/Configuration.cs b/src/Configuration.cs index c97cb76..9e74000 100644 --- a/src/Configuration.cs +++ b/src/Configuration.cs @@ -10,234 +10,139 @@ namespace Unity.Microsoft.DependencyInjection { - public static class Configuration - { - public static void Register(IServiceCollection services, IUnityContainer _container) + public static class Configuration { - _container.RegisterType(); - _container.RegisterType(); - _container.RegisterType(); + static Aggregates _aggregates; - RegisterEnumerable(_container); - - HashSet aggregateTypes = GetAggregateTypes(services); + public static IServiceProvider Configure(this IUnityContainer container, IServiceCollection services) + { + container.AddNewExtension(); - MethodInfo registerInstance = RegisterInstance(); + var provider = new ServiceProvider(container); - Func lifetime = GetLifetime(); + var aggregateTypes = GetAggregateTypes(services); - // Configure all registrations into Unity - foreach (ServiceDescriptor serviceDescriptor in services) - { - RegisterType( - _container, - lifetime, - serviceDescriptor, - aggregateTypes, - registerInstance); - } - } + var aggregateList = aggregateTypes.Select(t => new Aggregate(t, container)).ToList(); + _aggregates = new Aggregates(aggregateList); + container.RegisterInstance(_aggregates); - private static MethodInfo RegisterInstance() - { - return - typeof(UnityContainerExtensions) - .GetRuntimeMethods() - .Single(o => - o.IsStatic && - o.IsPublic && - o.IsGenericMethod && - o.Name == "RegisterInstance" && - o.GetParameters().Length == 4); - } + // Configure all registrations into Unity + foreach (var serviceDescriptor in services) + { + container.RegisterType(serviceDescriptor, _aggregates); + } + _aggregates.Register(); - private static HashSet GetAggregateTypes(IServiceCollection services) - { - var aggregateTypes = new HashSet - ( - services.GroupBy - ( - serviceDescriptor => serviceDescriptor.ServiceType, - serviceDescriptor => serviceDescriptor - ) - .Where(typeGrouping => typeGrouping.Count() > 1) - .Select(type => type.Key) - ); - - return aggregateTypes; - } + container.RegisterInstance(provider); + container.RegisterType(new HierarchicalLifetimeManager()); + + return provider; + } - private static void RegisterEnumerable(IUnityContainer _container) - { - _container.RegisterType - ( - typeof(IEnumerable<>), - new InjectionFactory - ( - (container, enumerableType, name) => - { - Type type = enumerableType.GenericTypeArguments.Single(); - Type genericType = type.GetGenericTypeDefinition(); - - object[] allInstances = container.ResolveAll(type).Concat - ( - _container.IsRegistered(type) || - type.GenericTypeArguments.Any() && - _container.IsRegistered(genericType) - ? new[] {container.Resolve(type)} - : new object[] { } - ) - .ToArray(); - - return - typeof(Enumerable).GetRuntimeMethod("OfType", new[] {typeof(object[])}) - .MakeGenericMethod(type) - .Invoke(null, new object[] {allInstances}); - } - ) - ); - } + internal static void Register(this IUnityContainer container, + ServiceDescriptor service, string qualifier) + { + if (service.ImplementationType != null) + { + RegisterImplementation(container, service, qualifier); + } + else if (service.ImplementationFactory != null) + { + RegisterFactory(container, service, qualifier); + } + else if (service.ImplementationInstance != null) + { + RegisterSingleton(container, service, qualifier); + } + else + { + throw new InvalidOperationException("Unsupported registration type"); + } + } - private static Func GetLifetime() - { - return serviceDescriptor => - { - switch (serviceDescriptor.Lifetime) + private static HashSet GetAggregateTypes(IServiceCollection services) { - case ServiceLifetime.Scoped: - return new HierarchicalLifetimeManager(); + var aggregateTypes = new HashSet + ( + services. + GroupBy + ( + serviceDescriptor => serviceDescriptor.ServiceType, + serviceDescriptor => serviceDescriptor + ). + Where(typeGrouping => typeGrouping.Count() > 1). + Select(type => type.Key) + ); + return aggregateTypes; + } - case ServiceLifetime.Singleton: - return new ContainerControlledLifetimeManager(); + - case ServiceLifetime.Transient: - return new TransientLifetimeManager(); + private static void RegisterType(this IUnityContainer container, + ServiceDescriptor serviceDescriptor, Aggregates aggregates) + { + var aggregate = aggregates.Get(serviceDescriptor.ServiceType); + if (aggregate != null) + aggregate.AddService(serviceDescriptor); + else + container.Register(serviceDescriptor, null); + } - default: - throw new NotImplementedException($"Unsupported lifetime manager type '{serviceDescriptor.Lifetime}'"); + private static void RegisterImplementation(this IUnityContainer container, + ServiceDescriptor serviceDescriptor, string qualifier) + { + container.RegisterType(serviceDescriptor.ServiceType, + serviceDescriptor.ImplementationType, + qualifier, + serviceDescriptor.GetLifetime(container)); } - }; - } - private static void RegisterType( - IUnityContainer _container, - Func fetchLifetime, - ServiceDescriptor serviceDescriptor, - ICollection aggregateTypes, - MethodInfo miRegisterInstanceOpen) - { - LifetimeManager lifetimeManager = fetchLifetime(serviceDescriptor); - bool isAggregateType = aggregateTypes.Contains(serviceDescriptor.ServiceType); - - if (serviceDescriptor.ImplementationType != null) - { - RegisterImplementation(_container, serviceDescriptor, isAggregateType, lifetimeManager); - } - else if (serviceDescriptor.ImplementationFactory != null) - { - RegisterFactory(_container, serviceDescriptor, isAggregateType, lifetimeManager); - } - else if (serviceDescriptor.ImplementationInstance != null) - { - RegisterSingleton(_container, serviceDescriptor, miRegisterInstanceOpen, isAggregateType, lifetimeManager); - } - else - { - throw new InvalidOperationException("Unsupported registration type"); - } - } + private static void RegisterFactory(this IUnityContainer container, + ServiceDescriptor serviceDescriptor, string qualifier) + { + container.RegisterType(serviceDescriptor.ServiceType, qualifier, serviceDescriptor.GetLifetime(container), + new InjectionFactory(scope => + { + var serviceProvider = serviceDescriptor.Lifetime == ServiceLifetime.Scoped + ? scope.Resolve() + : container.Resolve(); + var instance = serviceDescriptor.ImplementationFactory(serviceProvider); + return instance; + })); + } - private static void RegisterImplementation( - IUnityContainer _container, - ServiceDescriptor serviceDescriptor, - bool isAggregateType, - LifetimeManager lifetimeManager) - { - if (isAggregateType) - { - _container.RegisterType( - serviceDescriptor.ServiceType, - serviceDescriptor.ImplementationType, - serviceDescriptor.ImplementationType.AssemblyQualifiedName, - lifetimeManager); - } - else - { - _container.RegisterType( - serviceDescriptor.ServiceType, - serviceDescriptor.ImplementationType, - lifetimeManager); - } - } + private static void RegisterSingleton(this IUnityContainer container, + ServiceDescriptor serviceDescriptor, string qualifier) + { + container.RegisterInstance(serviceDescriptor.ServiceType, + qualifier, + serviceDescriptor.ImplementationInstance, + serviceDescriptor.GetLifetime(container)); + } - private static void RegisterFactory( - IUnityContainer _container, - ServiceDescriptor serviceDescriptor, - bool isAggregateType, - LifetimeManager lifetimeManager) - { - if (isAggregateType) - { - _container.RegisterType - ( - serviceDescriptor.ServiceType, - serviceDescriptor.ImplementationType.AssemblyQualifiedName, - lifetimeManager, - new InjectionFactory - ( - container => + internal static bool CanResolve(this IUnityContainer container, Type type) + { + if (type.IsClass && !type.IsAbstract) { - var serviceProvider = container.Resolve(); - object instance = serviceDescriptor.ImplementationFactory(serviceProvider); - return instance; + if (typeof(Delegate).IsAssignableFrom(type) || typeof(string) == type || type.IsEnum + || type.IsArray || type.IsPrimitive) + { + return container.IsRegistered(type); + } + return true; } - ) - ); - } - else - { - _container.RegisterType - ( - serviceDescriptor.ServiceType, - lifetimeManager, - new InjectionFactory - ( - container => + + if (type.IsGenericType) { - var serviceProvider = container.Resolve(); - object instance = serviceDescriptor.ImplementationFactory(serviceProvider); - return instance; + var gerericType = type.GetGenericTypeDefinition(); + if ((gerericType == typeof(IEnumerable<>)) || + container.IsRegistered(gerericType)) + { + return true; + } } - ) - ); - } - } - private static void RegisterSingleton( - IUnityContainer _container, - ServiceDescriptor serviceDescriptor, - MethodInfo miRegisterInstanceOpen, - bool isAggregateType, - LifetimeManager lifetimeManager) - { - if (isAggregateType) - { - miRegisterInstanceOpen - .MakeGenericMethod(serviceDescriptor.ServiceType) - .Invoke(null, - new[] - { - _container, serviceDescriptor.ImplementationType.AssemblyQualifiedName, - serviceDescriptor.ImplementationInstance, lifetimeManager - }); - } - else - { - _container.RegisterInstance( - serviceDescriptor.ServiceType, - serviceDescriptor.ImplementationInstance, - lifetimeManager); - } + return container.IsRegistered(type); + } } - } } \ No newline at end of file diff --git a/src/ConstructorSelectorPolicy.cs b/src/ConstructorSelectorPolicy.cs new file mode 100644 index 0000000..5ec6d1d --- /dev/null +++ b/src/ConstructorSelectorPolicy.cs @@ -0,0 +1,173 @@ +using Unity; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Unity.Policy; +using Unity.ObjectBuilder.BuildPlan.Selection; +using Unity.Builder; +using Unity.Builder.Selection; +using Unity.Attributes; +using Unity.ResolverPolicy; + +namespace Unity.Microsoft.DependencyInjection +{ + public class ConstructorSelectorPolicy : IConstructorSelectorPolicy + { + DefaultUnityConstructorSelectorPolicy dependency = new DefaultUnityConstructorSelectorPolicy(); + + /// + /// Choose the constructor to call for the given type. + /// + /// Current build context + /// + /// The Microsoft.Practices.ObjectBuilder2.IPolicyList to add any generated resolver objects into. + /// + /// The chosen constructor. + public SelectedConstructor SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination) + { + ConstructorInfo ctor = FindDependencyConstructor(context); + if (ctor != null) + return CreateSelectedConstructor(ctor); + return dependency.SelectConstructor(context, resolverPolicyDestination); + } + + private ConstructorInfo FindDependencyConstructor(IBuilderContext context) + { + Type typeOfAttribute = typeof(T); + + IEnumerable constructors = context.BuildKey.Type.GetTypeInfo() + .DeclaredConstructors.Where(c => (!c.IsStatic) && c.IsPublic); + + ConstructorInfo[] injectionConstructors = constructors + .Where(ctor => ctor.IsDefined(typeOfAttribute, true)) + .ToArray(); + switch (injectionConstructors.Length) + { + case 0: return FindSingleConstructor(constructors) ?? Other(constructors.ToArray(), context); + case 1: return injectionConstructors[0]; + default: + throw new InvalidOperationException( + $"Existem multiplos construtores decorados com Inject para a classe " + + $"{context.BuildKey.Type.GetTypeInfo().Name}"); + } + } + + private static ConstructorInfo FindSingleConstructor(IEnumerable constructors) + { + if (constructors.Count() == 1) + return constructors.First(); + return null; + } + + private SelectedConstructor CreateSelectedConstructor(ConstructorInfo ctor) + { + var result = new SelectedConstructor(ctor); + foreach (ParameterInfo param in ctor.GetParameters()) + { + result.AddParameterResolver(ResolveParameter(param)); + } + return result; + } + + private ConstructorInfo Other(ConstructorInfo[] constructors, IBuilderContext context) + { + Array.Sort(constructors, (a, b) => + { + var qtd = b.GetParameters().Length.CompareTo(a.GetParameters().Length); + if (qtd == 0) + { + return b.GetParameters().Sum(p => p.ParameterType.IsInterface ? 1 : 0) + .CompareTo(a.GetParameters().Sum(p => p.ParameterType.IsInterface ? 1 : 0)); + } + return qtd; + }); + + ConstructorInfo bestConstructor = null; + HashSet bestConstructorParameterTypes = null; + for (var i = 0; i < constructors.Length; i++) + { + var parameters = constructors[i].GetParameters(); + + var can = CanBuildUp(parameters, context); + + if (can) + { + if (bestConstructor == null) + { + bestConstructor = constructors[i]; + } + else + { + // Since we're visiting constructors in decreasing order of number of parameters, + // we'll only see ambiguities or supersets once we've seen a 'bestConstructor'. + + if (bestConstructorParameterTypes == null) + { + bestConstructorParameterTypes = new HashSet( + bestConstructor.GetParameters().Select(p => p.ParameterType)); + } + + if (!bestConstructorParameterTypes.IsSupersetOf(parameters.Select(p => p.ParameterType))) + { + if (bestConstructorParameterTypes.All(p => p.IsInterface) + && !parameters.All(p => p.ParameterType.IsInterface)) + return bestConstructor; + + var msg = $"Falha ao procurar um construtor para {context.BuildKey.Type.FullName}\n" + + $"Há uma abiquidade entre os construtores"; + throw new InvalidOperationException(msg); + } + else + { + return bestConstructor; + } + } + } + } + + if (bestConstructor == null) + { + //return null; + throw new InvalidOperationException( + $"Construtor não encontrado para {context.BuildKey.Type.FullName}"); + } + else + { + return bestConstructor; + } + } + + private bool CanBuildUp(ParameterInfo[] parameters, IBuilderContext context) + { + return parameters.All(p => context.Container.CanResolve(p.ParameterType)); + } + + /// + /// + /// Create a Policy to inject a parameter. + /// + /// + /// Cria uma política para injeção de um parâmetro. + /// + /// + /// Parameter to be injeted. + /// The Resolver Policy. + public IResolverPolicy ResolveParameter(ParameterInfo parameter) + { + var optional = parameter.GetCustomAttribute(false) != null; + // parametros do construtor com attribute Dependency + var attrs2 = parameter.GetCustomAttributes(false).OfType().ToList(); + if (attrs2.Count > 0) + { + return attrs2[0].CreateResolver(parameter.ParameterType); + } + + // No attribute, just go back to the container for the default for that type. + if (optional) + return new OptionalDependencyResolverPolicy(parameter.ParameterType, null); + else + return new NamedTypeDependencyResolverPolicy(parameter.ParameterType, null); + } + } +} diff --git a/src/HierarchicalTransientLifetimeManager.cs b/src/HierarchicalTransientLifetimeManager.cs new file mode 100644 index 0000000..b53ff0c --- /dev/null +++ b/src/HierarchicalTransientLifetimeManager.cs @@ -0,0 +1,35 @@ +using Unity.Lifetime; + +namespace Unity.Microsoft.DependencyInjection +{ + /// + /// A special lifetime manager which works like , + /// except that in the presence of child containers, each child gets it's own instance + /// of the object, instead of sharing one in the common parent. + /// + internal class HierarchicalTransientLifetimeManager : HierarchicalLifetimeManager + { + private IUnityContainer _container; + + public HierarchicalTransientLifetimeManager(IUnityContainer container) + { + _container = container; + } + + public override void SetValue(object newValue, ILifetimeContainer container = null) + { + _container.Resolve().Add(newValue); + } + + public override object GetValue(ILifetimeContainer container = null) + { + return null; + } + + protected override void Dispose(bool disposing) + { + _container = null; + base.Dispose(disposing); + } + } +} \ No newline at end of file diff --git a/src/MDIExtension.cs b/src/MDIExtension.cs new file mode 100644 index 0000000..ad36dfd --- /dev/null +++ b/src/MDIExtension.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Unity.Extension; +using Unity.Policy; + +namespace Unity.Microsoft.DependencyInjection +{ + internal class MDIExtension : UnityContainerExtension + { + protected override void Initialize() + { + Context.Policies.SetDefault(new ConstructorSelectorPolicy()); + } + } +} diff --git a/src/ServiceDescriptorExtensions.cs b/src/ServiceDescriptorExtensions.cs new file mode 100644 index 0000000..bea8673 --- /dev/null +++ b/src/ServiceDescriptorExtensions.cs @@ -0,0 +1,43 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using Unity.Lifetime; + +namespace Unity.Microsoft.DependencyInjection +{ + internal static class ServiceDescriptorExtensions + { + internal static Type GetImplementationType(this ServiceDescriptor service) + { + if (service.ImplementationType != null) + { + return service.ImplementationType; + } + else if (service.ImplementationInstance != null) + { + return service.ImplementationInstance.GetType(); + } + else if (service.ImplementationFactory != null) + { + var typeArguments = service.ImplementationFactory.GetType().GenericTypeArguments; + return typeArguments[1]; + } + return null; + } + + internal static LifetimeManager GetLifetime(this ServiceDescriptor serviceDescriptor, IUnityContainer container) + { + switch (serviceDescriptor.Lifetime) + { + case ServiceLifetime.Scoped: + return new HierarchicalLifetimeManager(); + case ServiceLifetime.Singleton: + return new ContainerControlledLifetimeManager(); + case ServiceLifetime.Transient: + return new HierarchicalTransientLifetimeManager(container); + default: + throw new NotImplementedException( + $"Unsupported lifetime manager type '{serviceDescriptor.Lifetime}'"); + } + } + } +} diff --git a/src/ServiceProvider.cs b/src/ServiceProvider.cs index d22d872..8d57613 100644 --- a/src/ServiceProvider.cs +++ b/src/ServiceProvider.cs @@ -1,19 +1,54 @@ -using System; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using Unity.Lifetime; namespace Unity.Microsoft.DependencyInjection { - public class ServiceProvider : IServiceProvider - { - private readonly IUnityContainer container; - - public ServiceProvider(IUnityContainer container) + public class ServiceProvider : IServiceProvider, IServiceScopeFactory, IDisposable { - this.container = container; - } + protected IUnityContainer container; + private static Type enumerableType = typeof(IEnumerable<>); - public object GetService(Type serviceType) - { - return container.Resolve(serviceType); + public ServiceProvider(IUnityContainer container) + { + this.container = container; //ExternallyControlledLifetimeManager + container.RegisterInstance(this, new ExternallyControlledLifetimeManager()); + } + + #region IServiceProvider + + public object GetService(Type serviceType) + { + if (!container.CanResolve(serviceType)) + return null; + var instance = container.Resolve(serviceType); + return instance; + } + + #endregion + + + #region IServiceScopeFactory + + public IServiceScope CreateScope() + { + return CreateScope(container); + } + + internal static IServiceScope CreateScope(IUnityContainer container) + { + return new ServiceScope(container); + } + + #endregion + + public void Dispose() + { + IDisposable disposable = container; + container = null; + disposable?.Dispose(); + GC.SuppressFinalize(this); + } } - } } \ No newline at end of file diff --git a/src/ServiceScope.cs b/src/ServiceScope.cs index 0242086..aba354a 100644 --- a/src/ServiceScope.cs +++ b/src/ServiceScope.cs @@ -4,21 +4,33 @@ namespace Unity.Microsoft.DependencyInjection { - public class ServiceScope : IServiceScope - { - private readonly IUnityContainer container; - - public ServiceScope(IUnityContainer container) + public class ServiceScope : IServiceScope { - this.container = container.CreateChildContainer(); - } + private IUnityContainer _container; + private ServiceProvider _provider; - public IServiceProvider ServiceProvider => - container.Resolve(); + IServiceProvider IServiceScope.ServiceProvider + { + get + { + if (_provider == null) + _provider = new ServiceProvider(_container.CreateChildContainer()); + return _provider; + } + } - public void Dispose() - { - container.Dispose(); + public ServiceScope(IUnityContainer container) + { + _container = container; + } + + public void Dispose() + { + var disposable = _provider; + _container = null; + _provider = null; + disposable?.Dispose(); + GC.SuppressFinalize(this); + } } - } } \ No newline at end of file diff --git a/src/ServiceScopeFactory.cs b/src/ServiceScopeFactory.cs index 5e3bfeb..ba0b92a 100644 --- a/src/ServiceScopeFactory.cs +++ b/src/ServiceScopeFactory.cs @@ -1,19 +1,19 @@ -using Microsoft.Extensions.DependencyInjection; +//using Microsoft.Extensions.DependencyInjection; -namespace Unity.Microsoft.DependencyInjection -{ - public class ServiceScopeFactory : IServiceScopeFactory - { - private readonly IUnityContainer container; +//namespace Unity.Microsoft.DependencyInjection +//{ +// public class ServiceScopeFactory : IServiceScopeFactory +// { +// private readonly IUnityContainer container; - public ServiceScopeFactory(IUnityContainer container) - { - this.container = container; - } +// public ServiceScopeFactory(IUnityContainer container) +// { +// this.container = container; +// } - public IServiceScope CreateScope() - { - return container.Resolve(); - } - } -} \ No newline at end of file +// public IServiceScope CreateScope() +// { +// return container.Resolve(); +// } +// } +//} \ No newline at end of file diff --git a/src/TransientObjectPool.cs b/src/TransientObjectPool.cs new file mode 100644 index 0000000..9bd630d --- /dev/null +++ b/src/TransientObjectPool.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Unity.Microsoft.DependencyInjection +{ + public class TransientObjectPool : IDisposable + { + private List objects = new List(); + + public void Add(object newValue) + { + objects.Add(newValue); + } + + public void Dispose() + { + foreach (IDisposable disposable in objects + .Select(o => o as IDisposable) + //.Where(o => null != o) + .Reverse()) + { + disposable.Dispose(); + } + + objects.Clear(); + objects = null; + GC.SuppressFinalize(this); + } + } +} diff --git a/src/Unity.Microsoft.DependencyInjection.csproj b/src/Unity.Microsoft.DependencyInjection.csproj index 086bb98..61c4837 100644 --- a/src/Unity.Microsoft.DependencyInjection.csproj +++ b/src/Unity.Microsoft.DependencyInjection.csproj @@ -19,17 +19,13 @@ Unity.Microsoft.DependencyInjection ..\..\Abstractions\src\Unity.Abstractions.csproj ..\..\Container\src\Unity.Container.csproj + netstandard2.0 - - netstandard1.0;net47 - true - - - netstandard1.0 - false - Full + + + TRACE;DEBUG @@ -43,7 +39,7 @@ - + @@ -51,7 +47,7 @@ - + diff --git a/tests/UnityDependencyInjectionTests.cs b/tests/UnityDependencyInjectionTests.cs index edb8d5e..ebab9cd 100644 --- a/tests/UnityDependencyInjectionTests.cs +++ b/tests/UnityDependencyInjectionTests.cs @@ -5,6 +5,14 @@ namespace Unity.Microsoft.DependencyInjection.Tests { + public class Tests : DependencyInjectionSpecificationTests + { + protected override IServiceProvider CreateServiceProvider(IServiceCollection serviceCollection) + { + var container = new UnityContainer(); + return container.Configure(serviceCollection); + } + } //public sealed class UnityDependencyInjectionTests : DependencyInjectionSpecificationTests //{ // ///