Commit 4e2a93fc authored by 阿星Plus's avatar 阿星Plus

😘 事件处理模块

parent 59e9635d
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.ExceptionServices;
namespace Plus.Collections namespace Plus.Collections
{ {
...@@ -139,5 +142,46 @@ namespace Plus.Collections ...@@ -139,5 +142,46 @@ namespace Plus.Collections
{ {
return dictionary.GetOrAdd(key, k => factory()); return dictionary.GetOrAdd(key, k => factory());
} }
public static Assembly GetAssembly(this Type type)
{
return type.GetTypeInfo().Assembly;
}
public static MethodInfo GetMethod(this Type type, string methodName, int pParametersCount = 0, int pGenericArgumentsCount = 0)
{
return type
.GetMethods()
.Where(m => m.Name == methodName).ToList()
.Select(m => new
{
Method = m,
Params = m.GetParameters(),
Args = m.GetGenericArguments()
})
.Where(x => x.Params.Length == pParametersCount
&& x.Args.Length == pGenericArgumentsCount
).Select(x => x.Method)
.First();
}
/// <summary>
/// Executes given <paramref name="action"/> by locking given <paramref name="source"/> object.
/// </summary>
/// <typeparam name="T">Type of the object (to be locked)</typeparam>
/// <param name="source">Source object (to be locked)</param>
/// <param name="action">Action (to be executed)</param>
public static void Locking<T>(this T source, Action<T> action) where T : class
{
lock (source)
{
action(source);
}
}
public static void ReThrow(this Exception exception)
{
ExceptionDispatchInfo.Capture(exception).Throw();
}
} }
} }
\ No newline at end of file
using Plus.Dependency;
namespace Plus.Configuration.Startup
{
/// <summary>
/// 用于配置 <see cref="IEventBus"/>.
/// </summary>
public interface IEventBusConfiguration
{
/// <summary>
/// True, to use <see cref="EventBus.Default"/>.
/// False, to create per <see cref="IIocManager"/>.
/// This is generally set to true. But, for unit tests,
/// it can be set to false.
/// Default: true.
/// </summary>
bool UseDefaultEventBus { get; set; }
}
}
\ No newline at end of file
...@@ -6,7 +6,7 @@ namespace Plus.Configuration.Startup ...@@ -6,7 +6,7 @@ namespace Plus.Configuration.Startup
/// <summary> /// <summary>
/// 在启动时的模块配置 /// 在启动时的模块配置
/// </summary> /// </summary>
public interface IPlusStartupConfiguration public interface IPlusStartupConfiguration: IDictionaryBasedConfig
{ {
/// <summary> /// <summary>
/// 获取与此配置关联的IOC管理器 /// 获取与此配置关联的IOC管理器
...@@ -26,5 +26,20 @@ namespace Plus.Configuration.Startup ...@@ -26,5 +26,20 @@ namespace Plus.Configuration.Startup
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns></returns> /// <returns></returns>
T Get<T>(); T Get<T>();
//IUnitOfWorkDefaultOptions UnitOfWork
//{
// get;
//}
//ICachingConfiguration Caching
//{
// get;
//}
//IValidationConfiguration Validation
//{
// get;
//}
} }
} }
\ No newline at end of file
This diff is collapsed.
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using Plus.Configuration.Startup;
using Plus.Dependency;
using Plus.Event.Bus.Factories;
using Plus.Event.Bus.Handlers;
using System.Reflection;
namespace Plus.Event.Bus
{
/// <summary>
/// 自动注册所有处理程序
/// </summary>
internal class EventBusInstaller : IWindsorInstaller
{
private readonly IIocResolver _iocResolver;
private readonly IEventBusConfiguration _eventBusConfiguration;
private IEventBus _eventBus;
public EventBusInstaller(IIocResolver iocResolver)
{
_iocResolver = iocResolver;
_eventBusConfiguration = iocResolver.Resolve<IEventBusConfiguration>();
}
public void Install(IWindsorContainer container, IConfigurationStore store)
{
if (_eventBusConfiguration.UseDefaultEventBus)
{
container.Register(
Component.For<IEventBus>().Instance(EventBus.Default).LifestyleSingleton()
);
}
else
{
container.Register(
Component.For<IEventBus>().ImplementedBy<EventBus>().LifestyleSingleton()
);
}
_eventBus = container.Resolve<IEventBus>();
container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;
}
private void Kernel_ComponentRegistered(string key, IHandler handler)
{
if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(handler.ComponentModel.Implementation))
{
return;
}
var interfaces = handler.ComponentModel.Implementation.GetTypeInfo().GetInterfaces();
foreach (var @interface in interfaces)
{
if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(@interface))
{
continue;
}
var genericArgs = @interface.GetGenericArguments();
if (genericArgs.Length == 1)
{
_eventBus.Register(genericArgs[0], new IocHandlerFactory(_iocResolver, handler.ComponentModel.Implementation));
}
}
}
}
}
\ No newline at end of file
using Plus.Event.Bus.Handlers;
namespace Plus.Event.Bus.Factories
{
/// <summary>
/// 为负责创建,获取和发布事件处理程序定义的接口
/// </summary>
public interface IEventHandlerFactory
{
/// <summary>
/// 获取事件处理程序
/// </summary>
/// <returns></returns>
IEventHandler GetHandler();
/// <summary>
/// 释放事件处理程序
/// </summary>
/// <param name="handler"></param>
void ReleaseHandler(IEventHandler handler);
}
}
\ No newline at end of file
using System;
namespace Plus.Event.Bus.Factories.Internals
{
/// <summary>
/// Used to unregister a <see cref="IEventHandlerFactory"/> on <see cref="Dispose"/> method.
/// </summary>
internal class FactoryUnregistrar : IDisposable
{
private readonly IEventBus _eventBus;
private readonly Type _eventType;
private readonly IEventHandlerFactory _factory;
public FactoryUnregistrar(IEventBus eventBus, Type eventType, IEventHandlerFactory factory)
{
_eventBus = eventBus;
_eventType = eventType;
_factory = factory;
}
public void Dispose()
{
_eventBus.Unregister(_eventType, _factory);
}
}
}
\ No newline at end of file
using Plus.Event.Bus.Handlers;
namespace Plus.Event.Bus.Factories.Internals
{
/// <summary>
/// This <see cref="IEventHandlerFactory"/> implementation is used to handle events by a single instance object.
/// </summary>
/// <remarks>
/// This class always gets the same single instance of handler.
/// </remarks>
internal class SingleInstanceHandlerFactory : IEventHandlerFactory
{
/// <summary>
/// The event handler instance.
/// </summary>
public IEventHandler HandlerInstance { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="handler"></param>
public SingleInstanceHandlerFactory(IEventHandler handler)
{
HandlerInstance = handler;
}
public IEventHandler GetHandler()
{
return HandlerInstance;
}
public void ReleaseHandler(IEventHandler handler)
{
}
}
}
\ No newline at end of file
using Plus.Event.Bus.Handlers;
using System;
namespace Plus.Event.Bus.Factories.Internals
{
/// <summary>
/// This <see cref="IEventHandlerFactory"/> implementation is used to handle events by a transient instance object.
/// </summary>
/// <remarks>
/// This class always creates a new transient instance of handler.
/// </remarks>
internal class TransientEventHandlerFactory<THandler> : IEventHandlerFactory
where THandler : IEventHandler, new()
{
/// <summary>
/// Creates a new instance of the handler object.
/// </summary>
/// <returns>The handler object</returns>
public IEventHandler GetHandler()
{
return new THandler();
}
public Type GetHandlerType()
{
return typeof(THandler);
}
/// <summary>
/// Disposes the handler object if it's <see cref="IDisposable"/>. Does nothing if it's not.
/// </summary>
/// <param name="handler">Handler to be released</param>
public void ReleaseHandler(IEventHandler handler)
{
if (handler is IDisposable)
{
(handler as IDisposable).Dispose();
}
}
}
}
\ No newline at end of file
using Plus.Dependency;
using Plus.Event.Bus.Handlers;
using System;
namespace Plus.Event.Bus.Factories
{
public class IocHandlerFactory : IEventHandlerFactory
{
private readonly IIocResolver _iocResolver;
public Type HandlerType { get; private set; }
public IocHandlerFactory(IIocResolver iocResolver, Type handlerType)
{
_iocResolver = iocResolver;
HandlerType = handlerType;
}
public IEventHandler GetHandler()
{
return (IEventHandler)_iocResolver.Resolve(HandlerType);
}
public void ReleaseHandler(IEventHandler handler)
{
_iocResolver.Release(handler);
}
}
}
\ No newline at end of file
using System.Threading.Tasks;
namespace Plus.Event.Bus.Handlers
{
/// <summary>
/// 定义一个处理 <see cref="IEventHandler{TEventData}"/> 类型事件的接口。
/// </summary>
/// <typeparam name="TEventData">要处理的事件类型</typeparam>
public interface IAsyncEventHandler<in TEventData> : IEventHandler
{
/// <summary>
/// 实现此方法处理事件
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
Task HandleEventAsync(TEventData eventData);
}
}
\ No newline at end of file
namespace Plus.Event.Bus.Handlers
{
/// <summary>
/// 事件处理接口
/// </summary>
public interface IEventHandler
{
}
}
\ No newline at end of file
namespace Plus.Event.Bus.Handlers
{
/// <summary>
/// 定义一个处理 <see cref="IEventHandler{TEventData}"/> 类型事件的接口。
/// </summary>
/// <typeparam name="TEventData">要处理的事件类型</typeparam>
public interface IEventHandler<in TEventData> : IEventHandler
{
/// <summary>
/// 实现此方法处理事件
/// </summary>
/// <param name="eventData">Event data</param>
void HandleEvent(TEventData eventData);
}
}
\ No newline at end of file
using Plus.Dependency;
using System;
namespace Plus.Event.Bus.Handlers.Internals
{
/// <summary>
/// 这个事件处理程序是一个适配器,能够使用一个操作作为 <see cref="IEventHandler{TEventData}"/> 实现
/// </summary>
/// <typeparam name="TEventData">事件类型</typeparam>
internal class ActionEventHandler<TEventData> :
IEventHandler<TEventData>,
ITransientDependency
{
public Action<TEventData> Action { get; private set; }
/// <summary>
/// 创建一个新的 <see cref="ActionEventHandler{TEventData}"/> 实例
/// </summary>
/// <param name="handler"></param>
public ActionEventHandler(Action<TEventData> handler)
{
Action = handler;
}
/// <summary>
/// 处理事件的操作
/// </summary>
/// <param name="eventData"></param>
public void HandleEvent(TEventData eventData)
{
Action(eventData);
}
}
}
\ No newline at end of file
using Plus.Dependency;
using System;
using System.Threading.Tasks;
namespace Plus.Event.Bus.Handlers.Internals
{
/// <summary>
/// 这个事件处理程序是一个适配器,能够使用一个操作作为 <see cref="IAsyncEventHandler{TEventData}"/> 实现
/// </summary>
/// <typeparam name="TEventData">事件类型</typeparam>
internal class AsyncActionEventHandler<TEventData> :
IAsyncEventHandler<TEventData>,
ITransientDependency
{
public Func<TEventData, Task> Action { get; private set; }
/// <summary>
/// 创建一个新的 <see cref="AsyncActionEventHandler{TEventData}"/> 实例
/// </summary>
/// <param name="handler"></param>
public AsyncActionEventHandler(Func<TEventData, Task> handler)
{
Action = handler;
}
/// <summary>
/// 处理事件的操作
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public async Task HandleEventAsync(TEventData eventData)
{
await Action(eventData);
}
}
}
\ No newline at end of file
using Plus.Event.Bus.Factories;
using Plus.Event.Bus.Handlers;
using System;
using System.Threading.Tasks;
namespace Plus.Event.Bus
{
/// <summary>
/// 定义事件接口
/// </summary>
public interface IEventBus
{
IDisposable Register<TEventData>(Action<TEventData> action) where TEventData : IEventData;
IDisposable Register<TEventData>(IEventHandler<TEventData> handler) where TEventData : IEventData;
IDisposable Register<TEventData, THandler>() where TEventData : IEventData where THandler : IEventHandler<TEventData>, new();
IDisposable Register(Type eventType, IEventHandler handler);
IDisposable Register<TEventData>(IEventHandlerFactory handlerFactory) where TEventData : IEventData;
IDisposable Register(Type eventType, IEventHandlerFactory handlerFactory);
void Unregister<TEventData>(Action<TEventData> action) where TEventData : IEventData;
void Unregister<TEventData>(IEventHandler<TEventData> handler) where TEventData : IEventData;
void Unregister(Type eventType, IEventHandler handler);
void Unregister<TEventData>(IEventHandlerFactory factory) where TEventData : IEventData;
void Unregister(Type eventType, IEventHandlerFactory factory);
void UnregisterAll<TEventData>() where TEventData : IEventData;
void UnregisterAll(Type eventType);
void Trigger<TEventData>(TEventData eventData) where TEventData : IEventData;
void Trigger<TEventData>(object eventSource, TEventData eventData) where TEventData : IEventData;
void Trigger(Type eventType, IEventData eventData);
void Trigger(Type eventType, object eventSource, IEventData eventData);
Task TriggerAsync<TEventData>(TEventData eventData) where TEventData : IEventData;
Task TriggerAsync<TEventData>(object eventSource, TEventData eventData) where TEventData : IEventData;
Task TriggerAsync(Type eventType, IEventData eventData);
Task TriggerAsync(Type eventType, object eventSource, IEventData eventData);
}
}
\ No newline at end of file
using System;
namespace Plus.Event.Bus
{
/// <summary>
/// 为所有事件定义接口。
/// </summary>
public interface IEventData
{
/// <summary>
/// 事件发生的时间
/// </summary>
DateTime EventTime { get; set; }
/// <summary>
/// 触发事件的对象
/// </summary>
object EventSource { get; set; }
}
}
\ No newline at end of file
namespace Plus.Event.Bus
{
/// <summary>
/// 此接口必须由具有单个泛型参数的事件数据类实现
/// </summary>
public interface IEventDataWithInheritableGenericArgument
{
/// <summary>
/// 获取创建该类的参数
/// </summary>
/// <returns></returns>
object[] GetConstructorArgs();
}
}
\ No newline at end of file
using System;
namespace Plus
{
/// <summary>
/// 生成GUID接口
/// </summary>
public interface IGuidGenerator
{
/// <summary>
/// 创建GUID
/// </summary>
Guid Create();
}
}
\ No newline at end of file
using Plus.Modules; using Castle.MicroKernel.Registration;
using Plus.Collections;
using Plus.Configuration.Startup;
using Plus.Dependency;
using Plus.Event.Bus;
using Plus.Modules;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.IO;
using System.Linq.Expressions;
namespace Plus namespace Plus
{ {
public class PlusLeadershipModule : PlusModule public class PlusLeadershipModule : PlusModule
{ {
public override void PreInitialize()
{
IocManager.AddRegistrar(new BasicConventionalRegistrar());
ConfigureCaches();
AddIgnoredTypes();
AddMethodParameterValidators();
}
public override void Initialize()
{
foreach (Action value in ((PlusStartupConfiguration)Configuration).ServiceReplaceActions.Values)
{
value();
}
IocManager.IocContainer.Install(new EventBusInstaller(IocManager));
IocManager.RegisterAssembly(typeof(PlusLeadershipModule).GetAssembly());
}
public override void PostInitialize()
{
RegisterMissingComponents();
}
public override void Shutdown()
{
}
private void RegisterMissingComponents()
{
if (!IocManager.IsRegistered<IGuidGenerator>())
{
IocManager.IocContainer.Register(
Component
.For<IGuidGenerator, SequentialGuidGenerator>()
.Instance(SequentialGuidGenerator.Instance)
);
}
//IocManager.RegisterIfNot<IUnitOfWork, NullUnitOfWork>(DependencyLifeStyle.Transient);
//IocManager.RegisterIfNot<IUnitOfWorkFilterExecuter, NullUnitOfWorkFilterExecuter>();
}
private void AddMethodParameterValidators()
{
//Configuration.Validation.Validators.Add<DataAnnotationsValidator>();
//Configuration.Validation.Validators.Add<ValidatableObjectValidator>();
}
private void AddIgnoredTypes()
{
var commonIgnoredTypes = new[]
{
typeof(Stream),
typeof(Expression)
};
foreach (var ignoredType in commonIgnoredTypes)
{
//Configuration.Auditing.IgnoredTypes.AddIfNotContains(ignoredType);
//Configuration.Validation.IgnoredTypes.AddIfNotContains(ignoredType);
}
var validationIgnoredTypes = new[] { typeof(Type) };
foreach (var ignoredType in validationIgnoredTypes)
{
//Configuration.Validation.IgnoredTypes.AddIfNotContains(ignoredType);
}
}
private void ConfigureCaches()
{
}
} }
} }
\ No newline at end of file
using System;
namespace Plus
{
public class SequentialGuidGenerator : IGuidGenerator
{
public static SequentialGuidGenerator Instance { get; } = new SequentialGuidGenerator();
public Guid Create()
{
byte[] array = Guid.NewGuid().ToByteArray();
DateTime dateTime = new DateTime(1900, 1, 1);
DateTime now = DateTime.Now;
TimeSpan timeSpan = new TimeSpan(now.Ticks - dateTime.Ticks);
TimeSpan timeOfDay = now.TimeOfDay;
byte[] bytes = BitConverter.GetBytes(timeSpan.Days);
byte[] bytes2 = BitConverter.GetBytes((long)(timeOfDay.TotalMilliseconds / 3.333333));
Array.Reverse(bytes);
Array.Reverse(bytes2);
Array.Copy(bytes, bytes.Length - 2, array, array.Length - 6, 2);
Array.Copy(bytes2, bytes2.Length - 4, array, array.Length - 4, 4);
return new Guid(array);
}
}
}
\ 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