Created
November 8, 2011 21:25
-
-
Save jpolvora/1349297 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
namespace Metavision.Infra | |
{ | |
/// <summary> | |
/// Service Locator simples | |
/// </summary> | |
public static class Container | |
{ | |
#region Fields | |
/// <summary> | |
/// Assemblies que serão incluídos na pesquisa de tipos por string | |
/// </summary> | |
internal static readonly List<Assembly> Assemblies = new List<Assembly>(); | |
/// <summary> | |
/// Dicionário que guarda instâncias singleton | |
/// </summary> | |
private static readonly Dictionary<Type, object> ActiveServices = new Dictionary<Type, object>(); | |
/// <summary> | |
/// Dicionário que guarda um ponteiro para um método que fabrica um determinado tipo | |
/// </summary> | |
private static readonly Dictionary<Type, Func<object>> Factories = new Dictionary<Type, Func<object>>(); | |
/// <summary> | |
/// objeto utilizado para lock de threads | |
/// </summary> | |
private static readonly object LockerObj = new object(); | |
/// <summary> | |
/// Dicionário que guarda configurações para o Container | |
/// </summary> | |
private static readonly Dictionary<Type, Type> ServiceEntries = new Dictionary<Type, Type>(); | |
/// <summary> | |
/// Dicionário que guarda tipos encontrados por string | |
/// </summary> | |
private static readonly Dictionary<string, Type> TypeDictionary = new Dictionary<string, Type>(); | |
#endregion Fields | |
#if !SILVERLIGHT | |
static Container() | |
{ | |
Assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies()); | |
} | |
#endif | |
#region Methods | |
public static void Initialize() | |
{ | |
} | |
public static void DisposeService<TService>() | |
{ | |
if (ActiveServices.ContainsKey(typeof(TService))) | |
{ | |
var disposable = ActiveServices[typeof(TService)] as IDisposable; | |
if (disposable != null) | |
{ | |
disposable.Dispose(); | |
} | |
} | |
ActiveServices[typeof(TService)] = null; | |
} | |
public static TServiceOut GetService<TService, TServiceOut>(bool singleton = true, object[] args = null) | |
where TServiceOut : class | |
{ | |
return GetService(typeof(TService), singleton, args) as TServiceOut; | |
} | |
public static TService GetService<TService>(bool singleton = true, object[] args = null) | |
{ | |
return (TService)GetService(typeof(TService), singleton, args); | |
} | |
public static object GetService(Type serviceType, bool singleton, object[] args = null) | |
{ | |
//thread safety | |
lock (LockerObj) | |
{ | |
if (serviceType == null) return null; | |
object service = null; | |
if (singleton && ActiveServices.ContainsKey(serviceType)) | |
{ | |
service = ActiveServices[serviceType]; | |
if (service != null) | |
return service; | |
} | |
try | |
{ | |
var typeToActivate = ServiceEntries.ContainsKey(serviceType) | |
? ServiceEntries[serviceType] | |
: serviceType; | |
if (!typeToActivate.IsInterface && !typeToActivate.IsAbstract) | |
{ | |
service = Factories.ContainsKey(serviceType) ? Factories[serviceType]() : Activator.CreateInstance(typeToActivate, args); | |
} | |
else if (typeToActivate.IsGenericType) | |
{ | |
var closedGeneric = ResolveOpenGeneric(typeToActivate); | |
if (closedGeneric != null) | |
{ | |
service = Activator.CreateInstance(closedGeneric, args); | |
} | |
} | |
} | |
finally | |
{ | |
if (singleton) ActiveServices[serviceType] = service; | |
} | |
return service; | |
} | |
} | |
public static void Register<TBase>(Func<TBase> factory = null) | |
where TBase : class | |
{ | |
Register<TBase, TBase>(factory); | |
} | |
public static void Register<TBase, TConcrete>(Func<TBase> factory = null) | |
where TBase : class | |
where TConcrete : class | |
{ | |
Register(typeof(TBase), typeof(TConcrete), factory as Func<object>); | |
} | |
public static void Register(Type tipoBase, Type tipoConcreto, Func<object> factory = null) | |
{ | |
if (tipoBase == null) throw new ArgumentNullException("tipoBase"); | |
if (tipoConcreto == null) | |
tipoConcreto = tipoBase; | |
ServiceEntries[tipoBase] = tipoConcreto; | |
ActiveServices[tipoBase] = null; | |
if (factory != null) | |
Factories[tipoBase] = factory; | |
} | |
public static TConcrete RegistraInstancia<TBase, TConcrete>(TConcrete instancia) | |
{ | |
ServiceEntries[typeof(TBase)] = typeof(TConcrete); | |
ActiveServices[typeof(TBase)] = instancia; | |
return instancia; | |
} | |
public static TBase RegistraInstancia<TBase>(TBase instancia) | |
{ | |
ServiceEntries[typeof(TBase)] = instancia.GetType(); | |
ActiveServices[typeof(TBase)] = instancia; | |
return instancia; | |
} | |
public static void Reset() | |
{ | |
ServiceEntries.Clear(); | |
ActiveServices.Clear(); | |
Factories.Clear(); | |
TypeDictionary.Clear(); | |
} | |
public static object TryResolve(string typeName, bool singleton) | |
{ | |
var foundType = SearchType(typeName); | |
return foundType != null ? GetService(foundType, singleton) : null; | |
} | |
public static Type SearchType(string typeName) | |
{ | |
Type foundType = null; | |
if (!string.IsNullOrEmpty(typeName)) | |
{ | |
if (TypeDictionary.ContainsKey(typeName)) | |
{ | |
return TypeDictionary[typeName]; | |
} | |
foundType = Type.GetType(typeName, false) ?? SearchInAssemblies(typeName); | |
//registra mesmo que não tenha encontrado o tipo | |
//para da proxima vez não perder tempo | |
TypeDictionary[typeName] = foundType; | |
} | |
return foundType; | |
} | |
private static Type SearchInAssemblies(string typeName) | |
{ | |
if (Assemblies != null) | |
{ | |
foreach (var assembly in Assemblies) | |
{ | |
var foundType = assembly.GetTypes().FirstOrDefault(t => t.Name == typeName); | |
if (foundType != null) return foundType; | |
} | |
} | |
return null; | |
} | |
private static Type ResolveOpenGeneric(Type type) | |
{ | |
var newTypeToResolve = type.GetGenericTypeDefinition(); //openGeneric | |
var extractedType = type.GetGenericArguments(); //parameter | |
var objetoRegistrado = ServiceEntries.FirstOrDefault(o => o.Key == newTypeToResolve); | |
if (objetoRegistrado.Key != null) | |
{ | |
var concreteType = objetoRegistrado.Value.MakeGenericType(extractedType); | |
return concreteType; | |
} | |
return null; | |
} | |
#endregion Methods | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment