-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathCastleContainer.cs
More file actions
173 lines (143 loc) · 5.21 KB
/
CastleContainer.cs
File metadata and controls
173 lines (143 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright (c) 2023, Phoenix Contact GmbH & Co. KG
// Licensed under the Apache License, Version 2.0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Moryx.Tools;
namespace Moryx.Container
{
/// <summary>
/// Class to load component specific windsor Container
/// </summary>
public class CastleContainer : IContainer
{
#region Constructors
private readonly IWindsorContainer _container;
private readonly IDictionary<Type, string> _strategies;
/// <summary>
/// Create instance without strategies
/// </summary>
public CastleContainer()
: this(new Dictionary<Type, string>())
{
}
/// <summary>
/// Create container with strategies
/// </summary>
/// <param name="strategies"></param>
public CastleContainer(IDictionary<Type, string> strategies)
{
_strategies = strategies;
// Boot up the container
_container = new WindsorContainer();
_container.AddFacility<TypedFactoryFacility>();
_container.AddFacility<MoryxFacility>(mf => mf.AddStrategies(strategies));
// Self registration for framework functionality
RegisterInstance(new[] { typeof(IContainer) }, this, null);
}
#endregion
/// <summary>
/// Resolve this named dependency
/// </summary>
public object Resolve(Type service, string name)
{
if(name == null && _strategies.ContainsKey(service))
name = _strategies[service];
// Resolve by name if given or determined
if (name != null && _container.Kernel.HasComponent(name))
return _container.Resolve(name, service);
// Resolve by type if found
if (_container.Kernel.HasComponent(service))
return _container.Resolve(service);
// Otherwise return null
return null;
}
/// <summary>
/// Resolve all implementations of this contract
/// </summary>
public Array ResolveAll(Type service)
{
return _container.ResolveAll(service);
}
/// <summary>
/// Get all implementations for a given component interface
/// </summary>
/// <returns></returns>
public IEnumerable<Type> GetRegisteredImplementations(Type service)
{
return _container.Kernel.GetHandlers(service).Select(handler => handler.ComponentModel.Implementation);
}
#region Register methods
/// <summary>
/// Register a component in the container
/// </summary>
public void Register(Type type, Type[] services, string name, LifeCycle lifeCycle)
{
// Make sure component is not registered yet
var componentName = name ?? type.FullName;
if (_container.Kernel.HasComponent(componentName))
return;
var registration = Component.For(services).ImplementedBy(type);
// Register name
if (!string.IsNullOrEmpty(name))
{
registration.Named(name);
}
// Register life style
switch (lifeCycle)
{
case LifeCycle.Transient:
registration.LifestyleTransient();
break;
case LifeCycle.Singleton:
registration.LifestyleSingleton();
break;
}
_container.Register(registration);
}
/// <summary>
/// Register factory interface
/// </summary>
public void RegisterFactory(Type factoryInterface, string name, Type selector)
{
var registration = Component.For(factoryInterface);
if (!string.IsNullOrEmpty(name))
{
registration.Named(name);
}
if (selector == null)
{
registration.AsFactory();
}
else
{
// Make sure selector is registered in the container
// TODO: Super dirty hack to use interfaces in component selectors
var selectorName = selector.IsClass ? selector.FullName : $"{selector.Namespace}.{selector.Name.Substring(1)}";
registration.AsFactory(config => config.SelectedWith(selectorName));
}
_container.Register(registration);
}
/// <summary>
/// Register instance in the container
/// </summary>
public void RegisterInstance(Type[] services, object instance, string name)
{
var registration = Component.For(services).Instance(instance);
if (!string.IsNullOrEmpty(name))
registration.Named(name);
_container.Register(registration);
}
#endregion
/// <see cref="IContainer"/>
public virtual void Destroy()
{
_container.Dispose();
}
}
}