Commit 59e9635d authored by 阿星Plus's avatar 阿星Plus

oook , PlusEngine 批量依赖注入 IOC管理等等

parent 71edd900
using System;
using System.Collections.Generic;
namespace Plus.Collections
{
/// <summary>
/// 扩展方法,后面要拿出来单独放一个项目中
/// </summary>
public static class Extensions
{
public static List<T> SortByDependencies<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getDependencies)
{
var sorted = new List<T>();
var visited = new Dictionary<T, bool>();
foreach (var item in source)
{
SortByDependenciesVisit(item, getDependencies, sorted, visited);
}
return sorted;
}
private static void SortByDependenciesVisit<T>(T item, Func<T, IEnumerable<T>> getDependencies, List<T> sorted, Dictionary<T, bool> visited)
{
var alreadyVisited = visited.TryGetValue(item, out bool inProcess);
if (alreadyVisited)
{
if (inProcess)
{
throw new ArgumentException("Cyclic dependency found! Item: " + item);
}
}
else
{
visited[item] = true;
var dependencies = getDependencies(item);
if (dependencies != null)
{
foreach (var dependency in dependencies)
{
SortByDependenciesVisit(dependency, getDependencies, sorted, visited);
}
}
visited[item] = false;
sorted.Add(item);
}
}
public static bool IsNullOrEmpty<T>(this ICollection<T> source)
{
return source == null || source.Count <= 0;
}
public static bool AddIfNotContains<T>(this ICollection<T> source, T item)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (source.Contains(item))
{
return false;
}
source.Add(item);
return true;
}
/// <summary>
/// This method is used to try to get a value in a dictionary if it does exists.
/// </summary>
/// <typeparam name="T">Type of the value</typeparam>
/// <param name="dictionary">The collection object</param>
/// <param name="key">Key</param>
/// <param name="value">Value of the key (or default value if key not exists)</param>
/// <returns>True if key does exists in the dictionary</returns>
internal static bool TryGetValue<T>(this IDictionary<string, object> dictionary, string key, out T value)
{
object valueObj;
if (dictionary.TryGetValue(key, out valueObj) && valueObj is T)
{
value = (T)valueObj;
return true;
}
value = default(T);
return false;
}
/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
{
TValue obj;
return dictionary.TryGetValue(key, out obj) ? obj : default(TValue);
}
/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> factory)
{
TValue obj;
if (dictionary.TryGetValue(key, out obj))
{
return obj;
}
return dictionary[key] = factory(key);
}
/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> factory)
{
return dictionary.GetOrAdd(key, k => factory());
}
}
}
\ No newline at end of file
using Plus.Collections;
using System;
using System.Collections.Generic;
namespace Plus.Configuration
{
public class DictionaryBasedConfig : IDictionaryBasedConfig
{
protected Dictionary<string, object> CustomSettings
{
get;
private set;
}
public object this[string name]
{
get { return CustomSettings.GetOrDefault(name); }
set { CustomSettings[name] = value; }
}
protected DictionaryBasedConfig()
{
CustomSettings = new Dictionary<string, object>();
}
public T Get<T>(string name)
{
object obj = this[name];
return (obj == null) ? default(T) : ((T)Convert.ChangeType(obj, typeof(T)));
}
public void Set<T>(string name, T value)
{
this[name] = value;
}
public object Get(string name)
{
return Get(name, null);
}
public object Get(string name, object defaultValue)
{
object obj = this[name];
if (obj == null)
{
return defaultValue;
}
return this[name];
}
public T Get<T>(string name, T defaultValue)
{
return (T)Get(name, (object)defaultValue);
}
public T GetOrCreate<T>(string name, Func<T> creator)
{
object obj = Get(name);
if (obj == null)
{
obj = creator();
Set(name, obj);
}
return (T)obj;
}
}
}
\ No newline at end of file
using System;
namespace Plus.Configuration
{
public interface IDictionaryBasedConfig
{
void Set<T>(string name, T value);
object Get(string name);
T Get<T>(string name);
object Get(string name, object defaultValue);
T Get<T>(string name, T defaultValue);
T GetOrCreate<T>(string name, Func<T> creator);
}
}
\ No newline at end of file
using Plus.Dependency;
using System;
namespace Plus.Configuration.Startup
{
/// <summary>
/// 在启动时的模块配置
/// </summary>
public interface IPlusStartupConfiguration
{
/// <summary>
/// 获取与此配置关联的IOC管理器
/// </summary>
IIocManager IocManager { get; }
/// <summary>
/// 用于替换服务类型
/// </summary>
/// <param name="type"></param>
/// <param name="replaceAction"></param>
void ReplaceService(Type type, Action replaceAction);
/// <summary>
/// 获取配置对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
T Get<T>();
}
}
\ No newline at end of file
using Plus.Dependency;
using System;
using System.Collections.Generic;
namespace Plus.Configuration.Startup
{
public class PlusStartupConfiguration : DictionaryBasedConfig, IPlusStartupConfiguration, IDictionaryBasedConfig
{
public IIocManager IocManager
{
get;
private set;
}
public Dictionary<Type, Action> ServiceReplaceActions
{
get;
private set;
}
public PlusStartupConfiguration(IIocManager iocManager)
{
IocManager = iocManager;
}
public void Initialize()
{
ServiceReplaceActions = new Dictionary<Type, Action>();
}
public void ReplaceService(Type type, Action replaceAction)
{
ServiceReplaceActions[type] = replaceAction;
}
public T Get<T>()
{
return GetOrCreate(typeof(T).FullName, () => IocManager.Resolve<T>());
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
namespace Plus.Dependency
{
public class ConventionalRegistrationConfig : DictionaryBasedConfig
{
/// <summary>
/// Install all <see cref="IInterceptor"/> implementations automatically or not.
/// Default: true.
/// </summary>
public bool InstallInstallers { get; set; }
/// <summary>
/// Creates a new <see cref="ConventionalRegistrationConfig"/> object.
/// </summary>
public ConventionalRegistrationConfig()
{
InstallInstallers = true;
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace Plus.Dependency
{
public interface IConventionalRegistrationContext
{
/// <summary>
/// Gets the registering Assembly.
/// </summary>
Assembly Assembly { get; }
/// <summary>
/// Reference to the IOC Container to register types.
/// </summary>
IIocManager IocManager { get; }
/// <summary>
/// Registration configuration.
/// </summary>
ConventionalRegistrationConfig Config { get; }
}
}
\ No newline at end of file
......@@ -4,7 +4,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Plus.Dependency
{
......@@ -39,7 +38,7 @@ namespace Plus.Dependency
public void RegisterAssembly(Assembly assembly)
{
ConventionalRegistrationContext context = new ConventionalRegistrationContext(assembly, this);
var context = new RegistrationContext(assembly, this);
foreach (IDependencyRegistrar conventionalRegistrar in _conventionalRegistrars)
{
conventionalRegistrar.RegisterAssembly(context);
......@@ -91,36 +90,16 @@ namespace Plus.Dependency
return IocContainer.Resolve(type);
}
//public object Resolve(Type type, object argumentsAsAnonymousType)
//{
// return IocContainer.Resolve(type, argumentsAsAnonymousType);
//}
//public T Resolve<T>(object argumentsAsAnonymousType)
//{
// return IocContainer.Resolve<T>(argumentsAsAnonymousType);
//}
public T[] ResolveAll<T>()
{
return IocContainer.ResolveAll<T>();
}
//public T[] ResolveAll<T>(object argumentsAsAnonymousType)
//{
// return IocContainer.ResolveAll<T>(argumentsAsAnonymousType);
//}
public object[] ResolveAll(Type type)
{
return IocContainer.ResolveAll(type).Cast<object>().ToArray();
}
//public object[] ResolveAll(Type type, object argumentsAsAnonymousType)
//{
// return IocContainer.ResolveAll(type, argumentsAsAnonymousType).Cast<object>().ToArray();
//}
public void Release(object obj)
{
IocContainer.Release(obj);
......
......@@ -2,7 +2,7 @@
namespace Plus.Dependency
{
internal class ConventionalRegistrationContext : IConventionalRegistrationContext
internal class RegistrationContext : IRegistrationContext
{
/// <summary>
/// Gets the registering Assembly.
......@@ -15,15 +15,14 @@ namespace Plus.Dependency
public IIocManager IocManager { get; private set; }
/// <summary>
/// Registration configuration.
///
/// </summary>
public ConventionalRegistrationConfig Config { get; private set; }
internal ConventionalRegistrationContext(Assembly assembly, IIocManager iocManager, ConventionalRegistrationConfig config)
/// <param name="assembly"></param>
/// <param name="iocManager"></param>
internal RegistrationContext(Assembly assembly, IIocManager iocManager)
{
Assembly = assembly;
IocManager = iocManager;
Config = config;
}
}
}
\ No newline at end of file
......@@ -4,4 +4,10 @@
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Castle.Core" Version="4.4.0" />
<PackageReference Include="Castle.Windsor" Version="5.0.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Text;
using Castle.Core.Logging;
using Plus.Dependency;
namespace Plus
{
public class PlusEngine
{
private readonly bool _initialized = false;
private bool _initialized = false;
public IIocManager IocManager { get; private set; }
public ILogger Logger { get; private set; }
public static PlusEngine Instance { get; private set; }
static PlusEngine()
{
Instance = new PlusEngine();
}
public void Initialize(IIocManager iocManage)
{
if (!_initialized)
{
Logger = NullLogger.Instance;
IocManager = iocManage;
_initialized = true;
return;
}
throw new PlusException("PlusEngine 初始化");
}
public void PostInitialize()
{
if (_initialized)
{
}
}
public void Register<T>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) where T : class
{
IocManager.Register(typeof(T), typeof(T), lifeStyle);
}
public void Register<TType, TImpl>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton)
{
IocManager.Register(typeof(TType), typeof(TImpl), lifeStyle);
}
public T Resolve<T>() where T : class
{
return IocManager.Resolve<T>();
}
}
}
\ No newline at end of file
using Plus.Modules;
using System;
using System.Collections.Generic;
using System.Text;
namespace Plus
{
public class PlusLeadershipModule : PlusModule
{
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
using Castle.Core.Logging;
using Castle.MicroKernel.Registration;
using Plus.Configuration.Startup;
using Plus.Dependency;
using Plus.Dependency.Installers;
using Plus.Modules;
using System;
using System.Reflection;
namespace Plus
{
public class PlusStarter : IDisposable
{
public void Dispose()
protected bool IsDisposed;
private ILogger _logger;
private IPlusModuleManager _moduleManager;
public Type StartupModule
{
get;
}
public IIocManager IocManager
{
get;
}
private PlusStarter(Type startupModule, Action<PlusStarterOptions> optionsAction = null)
{
PlusStarterOptions uPrimeStarterOptions = new PlusStarterOptions();
optionsAction?.Invoke(uPrimeStarterOptions);
if (!((TypeInfo)typeof(PlusModule)).IsAssignableFrom(startupModule))
{
throw new ArgumentException("startupModule should be derived from PlusModule.");
}
StartupModule = startupModule;
IocManager = uPrimeStarterOptions.IocManager;
_logger = NullLogger.Instance;
AddInterceptorRegistrars();
}
public static PlusStarter Create<TStartupModule>(Action<PlusStarterOptions> optionsAction = null) where TStartupModule : PlusModule
{
return new PlusStarter(typeof(TStartupModule), optionsAction);
}
public static PlusStarter Create(Type startupModule, Action<PlusStarterOptions> optionsAction = null)
{
return new PlusStarter(startupModule, optionsAction);
}
public virtual void Initialize()
{
PlusEngine.Instance.Initialize(IocManager);
ResolveLogger();
try
{
RegisterStarter();
_logger.Debug("PlusStarter 初始化.");
PlusEngine.Instance.IocManager.IocContainer.Install(new PlusCoreInstaller());
PlusEngine.Instance.PostInitialize();
IocManager.Resolve<PlusStartupConfiguration>().Initialize();
_moduleManager = PlusEngine.Instance.Resolve<PlusModuleManager>();
_moduleManager.Initialize(StartupModule);
_moduleManager.StartModules();
_logger.Debug("PlusStarter 初始化完成.");
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString(), ex);
throw;
}
}
public virtual void Dispose()
{
if (!IsDisposed)
{
IsDisposed = true;
_moduleManager?.ShutdownModules();
}
}
private void ResolveLogger()
{
if (IocManager.IsRegistered<ILoggerFactory>())
{
_logger = IocManager.Resolve<ILoggerFactory>().Create(typeof(PlusStarter));
}
}
private void RegisterStarter()
{
if (!IocManager.IsRegistered<PlusStarter>())
{
IocManager.IocContainer.Register((IRegistration[])new IRegistration[1]
{
Component.For<PlusStarter>().Instance(this)
});
}
}
public void AddInterceptorRegistrars()
{
throw new NotImplementedException();
//ValidationInterceptorRegistrar.Initialize(IocManager);
//UnitOfWorkRegistrar.Initialize(IocManager);
}
}
}
\ No newline at end of file
using Plus.Dependency;
namespace Plus
{
public class PlusStarterOptions
{
public IIocManager IocManager { get; set; }
public PlusStarterOptions()
{
IocManager = Dependency.IocManager.Instance;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment