DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
ServiceContainer.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 
21 using DryIoc;
22 
23 namespace Deveel.Data.Services {
24  public class ServiceContainer : IScope, IServiceProvider {
25  private IContainer container;
26  private List<IRegistrationConfigurationProvider> registrationProviders;
27 
28  public ServiceContainer()
29  : this(null, null) {
30  }
31 
32  private ServiceContainer(ServiceContainer parent, string scopeName) {
33  if (parent != null) {
34  container = parent.container.OpenScope(scopeName)
35  .With(rules => rules.WithDefaultReuseInsteadOfTransient(Reuse.InCurrentNamedScope(scopeName)));
36 
37  ScopeName = scopeName;
38  } else {
39  container = new Container(Rules.Default
40  .WithDefaultReuseInsteadOfTransient(Reuse.Singleton)
41  .WithoutThrowOnRegisteringDisposableTransient());
42  }
43 
44  registrationProviders = new List<IRegistrationConfigurationProvider>();
45  }
46 
48  Dispose(false);
49  }
50 
51  object IServiceProvider.GetService(Type serviceType) {
52  return Resolve(serviceType, null);
53  }
54 
55  protected virtual void Dispose(bool disposing) {
56  if (disposing) {
57  lock (this) {
58  if (container != null)
59  container.Dispose();
60  }
61  }
62 
63  container = null;
64  }
65 
66  private string ScopeName { get; set; }
67 
68  public void Dispose() {
69  Dispose(true);
70  GC.SuppressFinalize(this);
71  }
72 
73  private void RegisterConfigurations() {
74  if (registrationProviders != null && registrationProviders.Count > 0) {
75  foreach (var provider in registrationProviders) {
76  RegisterConfiguration(provider);
77  }
78 
79  registrationProviders.Clear();
80  }
81  }
82 
84  var registration = new ServiceRegistration(provider.ServiceType, provider.ImplementationType) {
85  Scope = provider.ScopeName,
86  ServiceKey = provider.ServiceKey,
87  Instance = provider.Instance
88  };
89 
90  Register(registration);
91  }
92 
93  public IScope OpenScope(string name) {
94  RegisterConfigurations();
95  return new ServiceContainer(this, name);
96  }
97 
98  public object Resolve(Type serviceType, object name) {
99  if (serviceType == null)
100  throw new ArgumentNullException("serviceType");
101 
102  if (container == null)
103  throw new InvalidOperationException("The container was not initialized.");
104 
105  lock (this) {
106  return container.Resolve(serviceType, name, IfUnresolved.ReturnDefault);
107  }
108  }
109 
110  public IRegistrationConfiguration<TService> Bind<TService>() {
111  var config = new RegistrationConfiguration<TService>(this);
112  registrationProviders.Add(config);
113  return config;
114  }
115 
116  public IEnumerable ResolveAll(Type serviceType) {
117  if (serviceType == null)
118  throw new ArgumentNullException("serviceType");
119 
120  if (container == null)
121  throw new InvalidOperationException("The container was not initialized.");
122 
123  lock (this) {
124  return container.ResolveMany<object>(serviceType);
125  }
126  }
127 
128  public void Register(ServiceRegistration registration) {
129  if (registration == null)
130  throw new ArgumentNullException("registration");
131 
132  if (container == null)
133  throw new InvalidOperationException("The container was not initialized.");
134 
135  lock (this) {
136  var serviceType = registration.ServiceType;
137  var service = registration.Instance;
138  var serviceName = registration.ServiceKey;
139  var implementationType = registration.ImplementationType;
140 
141  var reuse = Reuse.Singleton;
142  if (!String.IsNullOrEmpty(ScopeName))
143  reuse = Reuse.InCurrentNamedScope(ScopeName);
144 
145  if (!String.IsNullOrEmpty(registration.Scope))
146  reuse = Reuse.InCurrentNamedScope(registration.Scope);
147 
148  if (service == null) {
149  container.Register(serviceType, implementationType, serviceKey: serviceName, reuse: reuse);
150  } else {
151  container.RegisterInstance(serviceType, service, serviceKey: serviceName, reuse: reuse);
152  }
153  }
154  }
155 
156  public bool Unregister(Type serviceType, object serviceName) {
157  if (serviceType == null)
158  throw new ArgumentNullException("serviceType");
159 
160  if (container == null)
161  throw new InvalidOperationException("The container was not initialized.");
162 
163  lock (this) {
164  container.Unregister(serviceType, serviceName);
165  return true;
166  }
167  }
168 
169  #region RegistrationConfiguration
170 
173  Container = container;
174  }
175 
176  public IRegistrationWithBindingConfiguration<TService, TImplementation> To<TImplementation>() where TImplementation : class, TService {
177  AssertNotBound();
178  ImplementationType = typeof (TImplementation);
179  IsBound = true;
181  }
182 
183  public IRegistrationWithBindingConfiguration<TService, TImplementation> ToInstance<TImplementation>(TImplementation instance) where TImplementation : class, TService {
184  AssertNotBound();
185  ImplementationType = typeof (TImplementation);
186  Instance = instance;
187  IsBound = true;
189  }
190 
191  public Type ServiceType {
192  get { return typeof (TService); }
193  }
194 
195  private void AssertNotBound() {
196  if (IsBound)
197  throw new InvalidOperationException("The registration was already bound.");
198  }
199 
200  public ServiceContainer Container { get; private set; }
201 
202  private bool IsBound { get; set; }
203 
204  public Type ImplementationType { get; set; }
205 
206  public object ServiceKey { get; set; }
207 
208  public string ScopeName { get; set; }
209 
210  public object Instance { get; private set; }
211  }
212 
213  #endregion
214 
215  #region RegistrationWithBindingConfiguration
216 
217  class RegistrationWithBindingConfiguration<TService, TImplementation> : IRegistrationWithBindingConfiguration<TService, TImplementation> {
219 
221  this.configuration = configuration;
222  }
223 
225  configuration.ScopeName = scopeName;
226  return this;
227  }
228 
230  configuration.ServiceKey = serviceKey;
231  return this;
232  }
233  }
234 
235  #endregion
236  }
237 }
object Resolve(Type serviceType, object name)
IRegistrationWithBindingConfiguration< TService, TImplementation > WithKey(object serviceKey)
List< IRegistrationConfigurationProvider > registrationProviders
void Register(ServiceRegistration registration)
bool Unregister(Type serviceType, object serviceName)
IRegistrationWithBindingConfiguration< TService, TImplementation > InScope(string scopeName)
void RegisterConfiguration(IRegistrationConfigurationProvider provider)
ServiceContainer(ServiceContainer parent, string scopeName)
IEnumerable ResolveAll(Type serviceType)
RegistrationWithBindingConfiguration(RegistrationConfiguration< TService > configuration)
virtual void Dispose(bool disposing)