Skip to content

Commit ba7e92c

Browse files
committed
Refactoring
1 parent aba2a43 commit ba7e92c

11 files changed

+249
-128
lines changed

src/Aggregate.cs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,41 +29,41 @@ public void AddService(ServiceDescriptor service)
2929

3030
public void Register()
3131
{
32-
foreach (var serv in Services)
33-
{
34-
var qualifier = serv.GetImplementationType().FullName;
35-
Container.Register(serv, qualifier);
36-
}
32+
//foreach (var serv in Services)
33+
//{
34+
// var qualifier = serv.GetImplementationType().FullName;
35+
// Container.Register(serv, qualifier);
36+
//}
3737

38-
Container.RegisterType(Type, Last.GetLifetime(Container),
39-
new InjectionFactory((c, t, s) =>
40-
{
41-
if (Last.ServiceType.GetTypeInfo().IsGenericTypeDefinition)
42-
return c.Resolve(t, Last.GetImplementationType().FullName);
43-
var instance = Resolve(c);
44-
return instance;
45-
}));
38+
//Container.RegisterType(Type, Last.GetLifetime(),
39+
// new InjectionFactory((c, t, s) =>
40+
// {
41+
// if (Last.ServiceType.GetTypeInfo().IsGenericTypeDefinition)
42+
// return c.Resolve(t, Last.GetImplementationType().FullName);
43+
// var instance = Resolve(c);
44+
// return instance;
45+
// }));
4646

47-
var enumType = typeof(IEnumerable<>).MakeGenericType(Type);
48-
Container.RegisterType(enumType, new HierarchicalTransientLifetimeManager(),
49-
new InjectionFactory(c =>
50-
{
51-
List<object> instances = new List<object>();
52-
foreach (var serv in Services)
53-
{
54-
if (!serv.ServiceType.GetTypeInfo().IsGenericTypeDefinition)
55-
{
56-
var qualifier = serv.GetImplementationType().FullName;
57-
var instance = Container.Resolve(serv.ServiceType, qualifier);
58-
instances.Add(instance);
59-
}
60-
}
61-
return typeof(Enumerable)
62-
.GetTypeInfo()
63-
.GetDeclaredMethod("Cast")
64-
.MakeGenericMethod(Type)
65-
.Invoke(null, new[] { instances });
66-
}));
47+
//var enumType = typeof(IEnumerable<>).MakeGenericType(Type);
48+
//Container.RegisterType(enumType, new HierarchicalTransientLifetimeManager(),
49+
// new InjectionFactory(c =>
50+
// {
51+
// List<object> instances = new List<object>();
52+
// foreach (var serv in Services)
53+
// {
54+
// if (!serv.ServiceType.GetTypeInfo().IsGenericTypeDefinition)
55+
// {
56+
// var qualifier = serv.GetImplementationType().FullName;
57+
// var instance = Container.Resolve(serv.ServiceType, qualifier);
58+
// instances.Add(instance);
59+
// }
60+
// }
61+
// return typeof(Enumerable)
62+
// .GetTypeInfo()
63+
// .GetDeclaredMethod("Cast")
64+
// .MakeGenericMethod(Type)
65+
// .Invoke(null, new[] { instances });
66+
// }));
6767
}
6868

6969
public object Resolve(IUnityContainer container)

src/Configuration.cs

Lines changed: 53 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,106 +4,90 @@
44
using System.Reflection;
55
using Microsoft.Extensions.DependencyInjection;
66
using Unity.Injection;
7+
using Unity.Lifetime;
78

89
namespace Unity.Microsoft.DependencyInjection
910
{
1011
internal static class Configuration
1112
{
12-
static List<Aggregate> _aggregates;
1313

14-
internal static void Configure(this IUnityContainer container, IServiceCollection services)
14+
internal static IUnityContainer AddServices(this IUnityContainer container, IServiceCollection services)
1515
{
16-
var aggregateTypes = GetAggregateTypes(services);
16+
var lifetime = container.Configure<MDIExtension>()
17+
.Lifetime;
1718

18-
_aggregates = aggregateTypes.Select(t => new Aggregate(t, container)).ToList();
19-
container.RegisterInstance(_aggregates);
20-
21-
// Configure all registrations into Unity
22-
foreach (var serviceDescriptor in services)
19+
foreach (var group in services.GroupBy(serviceDescriptor => serviceDescriptor.ServiceType,
20+
serviceDescriptor => serviceDescriptor)
21+
.Select(group => group.ToArray()))
2322
{
24-
container.RegisterType(serviceDescriptor, _aggregates);
25-
}
23+
// Register named types
24+
for (var i = 0; i < group.Length - 1; i++)
25+
{
26+
var descriptor = group[i];
27+
container.Register(descriptor, descriptor.GetRegistrationName(), lifetime);
28+
}
2629

27-
foreach (var type in _aggregates)
28-
{
29-
type.Register();
30+
// Register default types
31+
container.Register(group[group.Length - 1], null, lifetime);
3032
}
33+
34+
return container;
3135
}
3236

3337
internal static void Register(this IUnityContainer container,
34-
ServiceDescriptor service, string qualifier)
38+
ServiceDescriptor serviceDescriptor, string qualifier, ILifetimeContainer lifetime)
3539
{
36-
if (service.ImplementationType != null)
40+
if (serviceDescriptor.ImplementationType != null)
3741
{
38-
RegisterImplementation(container, service, qualifier);
42+
container.RegisterType(serviceDescriptor.ServiceType,
43+
serviceDescriptor.ImplementationType,
44+
qualifier,
45+
serviceDescriptor.GetLifetime(lifetime));
3946
}
40-
else if (service.ImplementationFactory != null)
47+
else if (serviceDescriptor.ImplementationFactory != null)
4148
{
42-
RegisterFactory(container, service, qualifier);
49+
container.RegisterType(serviceDescriptor.ServiceType,
50+
qualifier,
51+
serviceDescriptor.GetLifetime(lifetime),
52+
new InjectionFactory(scope =>
53+
{
54+
var serviceProvider = serviceDescriptor.Lifetime == ServiceLifetime.Scoped
55+
? scope.Resolve<IServiceProvider>()
56+
: container.Resolve<IServiceProvider>();
57+
var instance = serviceDescriptor.ImplementationFactory(serviceProvider);
58+
return instance;
59+
}));
4360
}
44-
else if (service.ImplementationInstance != null)
61+
else if (serviceDescriptor.ImplementationInstance != null)
4562
{
46-
RegisterSingleton(container, service, qualifier);
63+
container.RegisterInstance(serviceDescriptor.ServiceType,
64+
qualifier,
65+
serviceDescriptor.ImplementationInstance,
66+
serviceDescriptor.GetLifetime(lifetime));
4767
}
4868
else
4969
{
5070
throw new InvalidOperationException("Unsupported registration type");
5171
}
5272
}
5373

54-
private static HashSet<Type> GetAggregateTypes(IServiceCollection services)
55-
{
56-
var enumerable = services.GroupBy(serviceDescriptor => serviceDescriptor.ServiceType,
57-
serviceDescriptor => serviceDescriptor)
58-
.Where(typeGrouping => typeGrouping.Count() > 1)
59-
.Select(type => type.Key);
60-
61-
return new HashSet<Type>(enumerable);
62-
}
63-
64-
65-
66-
private static void RegisterType(this IUnityContainer container,
67-
ServiceDescriptor serviceDescriptor, List<Aggregate> aggregates)
68-
{
69-
var aggregate = aggregates.FirstOrDefault(a => a.Type == serviceDescriptor.ServiceType);
70-
if (aggregate != null)
71-
aggregate.AddService(serviceDescriptor);
72-
else
73-
container.Register(serviceDescriptor, null);
74-
}
75-
76-
private static void RegisterImplementation(this IUnityContainer container,
77-
ServiceDescriptor serviceDescriptor, string qualifier)
78-
{
79-
container.RegisterType(serviceDescriptor.ServiceType,
80-
serviceDescriptor.ImplementationType,
81-
qualifier,
82-
serviceDescriptor.GetLifetime(container));
83-
}
8474

85-
private static void RegisterFactory(this IUnityContainer container,
86-
ServiceDescriptor serviceDescriptor, string qualifier)
75+
internal static LifetimeManager GetLifetime(this ServiceDescriptor serviceDescriptor, ILifetimeContainer lifetime)
8776
{
88-
container.RegisterType(serviceDescriptor.ServiceType, qualifier, serviceDescriptor.GetLifetime(container),
89-
new InjectionFactory(scope =>
90-
{
91-
var serviceProvider = serviceDescriptor.Lifetime == ServiceLifetime.Scoped
92-
? scope.Resolve<IServiceProvider>()
93-
: container.Resolve<IServiceProvider>();
94-
var instance = serviceDescriptor.ImplementationFactory(serviceProvider);
95-
return instance;
96-
}));
77+
switch (serviceDescriptor.Lifetime)
78+
{
79+
case ServiceLifetime.Scoped:
80+
return new HierarchicalLifetimeManager();
81+
case ServiceLifetime.Singleton:
82+
return new InjectionSingletonLifetimeManager(lifetime);
83+
case ServiceLifetime.Transient:
84+
return new InjectionTransientLifetimeManager();
85+
default:
86+
throw new NotImplementedException(
87+
$"Unsupported lifetime manager type '{serviceDescriptor.Lifetime}'");
88+
}
9789
}
9890

99-
private static void RegisterSingleton(this IUnityContainer container,
100-
ServiceDescriptor serviceDescriptor, string qualifier)
101-
{
102-
container.RegisterInstance(serviceDescriptor.ServiceType,
103-
qualifier,
104-
serviceDescriptor.ImplementationInstance,
105-
serviceDescriptor.GetLifetime(container));
106-
}
10791

10892
internal static bool CanResolve(this IUnityContainer container, Type type)
10993
{

src/MDIExtension.cs renamed to src/Extension/MDIExtension.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Unity.Extension;
2+
using Unity.Lifetime;
23
using Unity.Policy;
34

45
namespace Unity.Microsoft.DependencyInjection
@@ -9,5 +10,7 @@ protected override void Initialize()
910
{
1011
Context.Policies.SetDefault<IConstructorSelectorPolicy>(new ConstructorSelectorPolicy());
1112
}
13+
14+
public ILifetimeContainer Lifetime => Context.Lifetime;
1215
}
1316
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
4+
using System.Threading;
5+
using Unity.Exceptions;
6+
using Unity.Lifetime;
7+
8+
namespace Unity.Microsoft.DependencyInjection.Lifetime
9+
{
10+
public class InjectionScopeLifetimeManager : HierarchicalLifetimeManager
11+
{
12+
}
13+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
using System;
2+
using System.Threading;
3+
using Unity.Exceptions;
4+
using Unity.Lifetime;
5+
6+
namespace Unity.Microsoft.DependencyInjection
7+
{
8+
public class InjectionSingletonLifetimeManager : LifetimeManager, IRequiresRecovery
9+
{
10+
#region Fields
11+
12+
protected object _value;
13+
private ILifetimeContainer _lifetime;
14+
private readonly object _lockObj = new object();
15+
16+
#endregion
17+
18+
19+
public InjectionSingletonLifetimeManager(ILifetimeContainer lifetime)
20+
{
21+
_lifetime = lifetime;
22+
}
23+
24+
25+
/// <summary>
26+
/// Retrieve a value from the backing store associated with this Lifetime policy.
27+
/// </summary>
28+
/// <returns>the object desired, or null if no such object is currently stored.</returns>
29+
/// <remarks>Calls to this method acquire a lock which is released only if a non-null value
30+
/// has been set for the lifetime manager.</remarks>
31+
public override object GetValue(ILifetimeContainer container = null)
32+
{
33+
Monitor.Enter(_lockObj);
34+
var result = SynchronizedGetValue(container);
35+
if (result != null)
36+
{
37+
Monitor.Exit(_lockObj);
38+
}
39+
return result;
40+
}
41+
42+
/// <summary>
43+
/// Performs the actual retrieval of a value from the backing store associated
44+
/// with this Lifetime policy.
45+
/// </summary>
46+
/// <returns>the object desired, or null if no such object is currently stored.</returns>
47+
/// <remarks>This method is invoked by <see cref="SynchronizedLifetimeManager.GetValue"/>
48+
/// after it has acquired its lock.</remarks>
49+
protected virtual object SynchronizedGetValue(ILifetimeContainer container)
50+
{
51+
return _value;
52+
}
53+
54+
55+
/// <summary>
56+
/// Stores the given value into backing store for retrieval later.
57+
/// </summary>
58+
/// <param name="newValue">The object being stored.</param>
59+
/// <param name="container">The container this value belongs to.</param>
60+
/// <remarks>Setting a value will attempt to release the lock acquired by
61+
/// <see cref="SynchronizedLifetimeManager.GetValue"/>.</remarks>
62+
public override void SetValue(object newValue, ILifetimeContainer container = null)
63+
{
64+
SynchronizedSetValue(newValue, container);
65+
TryExit();
66+
}
67+
68+
/// <summary>
69+
/// Performs the actual storage of the given value into backing store for retrieval later.
70+
/// </summary>
71+
/// <param name="newValue">The object being stored.</param>
72+
/// <param name="container"></param>
73+
/// <remarks>This method is invoked by <see cref="SynchronizedLifetimeManager.SetValue"/>
74+
/// before releasing its lock.</remarks>
75+
protected virtual void SynchronizedSetValue(object newValue, ILifetimeContainer container)
76+
{
77+
_value = newValue;
78+
if (_value is IDisposable disposable) _lifetime.Add(disposable);
79+
}
80+
81+
/// <summary>
82+
/// A method that does whatever is needed to clean up
83+
/// as part of cleaning up after an exception.
84+
/// </summary>
85+
/// <remarks>
86+
/// Don't do anything that could throw in this method,
87+
/// it will cause later recover operations to get skipped
88+
/// and play real havoc with the stack trace.
89+
/// </remarks>
90+
public void Recover()
91+
{
92+
TryExit();
93+
}
94+
95+
protected virtual void TryExit()
96+
{
97+
#if !NET40
98+
// Prevent first chance exception when abandoning a lock that has not been entered
99+
if (!Monitor.IsEntered(_lockObj)) return;
100+
#endif
101+
try
102+
{
103+
Monitor.Exit(_lockObj);
104+
}
105+
catch (SynchronizationLockException)
106+
{
107+
// Noop here - we don't hold the lock and that's ok.
108+
}
109+
}
110+
111+
public override void RemoveValue(ILifetimeContainer container = null)
112+
{
113+
TryExit();
114+
}
115+
116+
protected override LifetimeManager OnCreateLifetimeManager()
117+
{
118+
return new InjectionSingletonLifetimeManager(_lifetime);
119+
}
120+
}
121+
}

src/HierarchicalTransientLifetimeManager.cs renamed to src/Lifetime/InjectionTransientLifetimeManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Unity.Microsoft.DependencyInjection
88
/// except it makes container remember all Disposable objects it created. Once container
99
/// is disposed all these objects are disposed as well.
1010
/// </summary>
11-
internal class HierarchicalTransientLifetimeManager : LifetimeManager
11+
internal class InjectionTransientLifetimeManager : LifetimeManager
1212
{
1313
public override void SetValue(object newValue, ILifetimeContainer container = null)
1414
{
File renamed without changes.

0 commit comments

Comments
 (0)