This repository has been archived on 2023-03-29. You can view files and clone it, but cannot push or open issues or pull requests.
Sic02/FrameworkLocal/UIClient/Core/Container/SimpleContainer.cs

139 lines
5.3 KiB
C#
Raw Normal View History

2022-08-05 14:47:02 +08:00
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace OpenSEMI.Core.Container
{
public class w : IContainer
{
private readonly ConcurrentDictionary<Type, CachedTypeInfo> _serviceTypeLookup = new ConcurrentDictionary<Type, CachedTypeInfo>();
private readonly ConcurrentDictionary<Type, object> _serviceInstanceLookup = new ConcurrentDictionary<Type, object>();
private readonly ConcurrentDictionary<Type, Action<object>> _serviceTypeCallbackLookup = new ConcurrentDictionary<Type, Action<object>>();
#region IContainer Implementation
public void Register<TService, TImplementation>() where TImplementation : TService
{
_serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = typeof(TImplementation), IsSingleton = true };
}
public void Register<TService, TImplementation>(bool singleton = true) where TImplementation : TService
{
_serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = typeof(TImplementation), IsSingleton = singleton };
}
public void Register<TService>(Type implementationType, bool singleton = true)
{
if (implementationType == null)
throw new ArgumentNullException("implementationType cannot be null.");
_serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton };
}
public void Register<TService>(Type implementationType, Action<TService> callback, bool singleton = true)
{
if (implementationType == null)
throw new ArgumentNullException("serviceType cannot be null.");
_serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton };
if (callback != null)
_serviceTypeCallbackLookup[typeof(TService)] = (x) => callback((TService)x);
}
public void Register(Type serviceType, Type implementationType, bool singleton = true)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType cannot be null.");
if (implementationType == null)
throw new ArgumentNullException("serviceType cannot be null.");
if (!serviceType.IsAssignableFrom(implementationType))
throw new ArgumentException(string.Format("Service could not be registered. {0} does not implement {1}.", implementationType.Name, serviceType.Name));
_serviceTypeLookup[serviceType] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton };
}
public void Register<TService>(TService instance)
{
if (instance == null)
throw new ArgumentNullException("instance cannot be null.");
_serviceInstanceLookup[typeof(TService)] = instance;
}
public T Resolve<T>()
{
return (T)Resolve(typeof(T));
}
private object Resolve(Type type)
{
CachedTypeInfo containerType;
object instance = null;
// If the type isn't registered, register the type to itself.
if (!_serviceTypeLookup.TryGetValue(type, out containerType))
{
Register(type, type);
containerType = new CachedTypeInfo { Type = type, IsSingleton = true };
}
// TODO: Should it use the instance by default? I'd assume so initially.
// Check if the service has an instance in the list of instances, if so, return it here.
if (_serviceInstanceLookup.TryGetValue(type, out instance))
return instance;
var constructor = ConstructorCache.GetConstructor(containerType.Type);
if (constructor != null)
{
// Get constructor parameters.
var parameters = ParameterCache.GetParameters(constructor);
var parameterObjects = new List<object>();
foreach (var parameter in parameters)
{
parameterObjects.Add(Resolve(parameter.ParameterType));
}
var obj = Activator.CreateInstance(containerType.Type, parameterObjects.ToArray());
Action<object> callback;
if (_serviceTypeCallbackLookup.TryGetValue(type, out callback))
callback(obj);
if (containerType.IsSingleton)
_serviceInstanceLookup[type] = obj;
return obj;
}
else
{
// Return null rather than throw an exception for resolve failures.
// This null will happen when there are 0 constructors for the supplied type.
return null;
}
}
public bool IsRegistered<TService>()
{
if (_serviceTypeLookup.ContainsKey(typeof(TService)) || _serviceInstanceLookup.ContainsKey(typeof(TService)))
return true;
return false;
}
#endregion
#region IServiceProvider Implementation
public object GetService(Type serviceType)
{
return Resolve(serviceType);
}
#endregion
}
}