mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-01-24 05:42:10 +08:00
More work on Event Bus optimization
--HG-- branch : 1.x
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
@@ -24,11 +25,11 @@ namespace Orchard.Tests.Events {
|
||||
builder.RegisterType<StubEventHandler2>()
|
||||
.Named(typeof(ITestEventHandler).Name, typeof(IEventHandler))
|
||||
.Named(typeof(IEventHandler).Name, typeof(IEventHandler))
|
||||
.WithMetadata("Interfaces", typeof(StubEventHandler2).GetInterfaces().ToLookup(i => i.Name));
|
||||
.WithMetadata("Interfaces", typeof(StubEventHandler2).GetInterfaces().ToDictionary(i => i.Name));
|
||||
builder.RegisterInstance(_eventHandler)
|
||||
.Named(typeof(ITestEventHandler).Name, typeof(IEventHandler))
|
||||
.Named(typeof(IEventHandler).Name, typeof(IEventHandler))
|
||||
.WithMetadata("Interfaces", typeof(StubEventHandler).GetInterfaces().ToLookup(i => i.Name));
|
||||
.WithMetadata("Interfaces", typeof(StubEventHandler).GetInterfaces().ToDictionary(i => i.Name));
|
||||
|
||||
_container = builder.Build();
|
||||
_eventBus = _container.Resolve<IEventBus>();
|
||||
@@ -169,8 +170,7 @@ namespace Orchard.Tests.Events {
|
||||
Assert.That(results, Has.Some.EqualTo("alpha"));
|
||||
Assert.That(results, Has.Some.EqualTo("[42,alpha]"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public interface ITestEventHandler : IEventHandler {
|
||||
void Increment();
|
||||
void Sum(int a);
|
||||
|
||||
@@ -66,12 +66,12 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
.InstancePerLifetimeScope();
|
||||
|
||||
foreach (var interfaceType in item.Type.GetInterfaces()
|
||||
.Where(itf => typeof(IDependency).IsAssignableFrom(itf)
|
||||
.Where(itf => typeof(IDependency).IsAssignableFrom(itf)
|
||||
&& !typeof(IEventHandler).IsAssignableFrom(itf))) {
|
||||
registration = registration.As(interfaceType);
|
||||
if (typeof(ISingletonDependency).IsAssignableFrom(interfaceType)) {
|
||||
registration = registration.InstancePerMatchingLifetimeScope("shell");
|
||||
}
|
||||
}
|
||||
else if (typeof(IUnitOfWorkDependency).IsAssignableFrom(interfaceType)) {
|
||||
registration = registration.InstancePerMatchingLifetimeScope("work");
|
||||
}
|
||||
@@ -83,11 +83,16 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
if (typeof(IEventHandler).IsAssignableFrom(item.Type)) {
|
||||
var interfaces = item.Type.GetInterfaces();
|
||||
foreach (var interfaceType in interfaces) {
|
||||
// Register named instance for each interface, for efficient filtering inside event bus
|
||||
registration = registration.Named(interfaceType.Name, typeof (IEventHandler));
|
||||
|
||||
// register named instance for each interface, for efficient filtering inside event bus
|
||||
// IEventHandler subclasses onnly
|
||||
if (interfaceType.IsSubclassOf(typeof(IEventHandler)) && interfaceType != typeof(IEventHandler)) {
|
||||
registration = registration.Named(interfaceType.Name, typeof(IEventHandler));
|
||||
}
|
||||
}
|
||||
// Keep interfaces in metadata for performance
|
||||
registration = registration.WithMetadata("Interfaces", interfaces.ToLookup(i => i.Name));
|
||||
|
||||
// keep mapping between interface name and actual type
|
||||
registration = registration.WithMetadata("Interfaces", interfaces.ToDictionary(i => i.Name));
|
||||
}
|
||||
|
||||
foreach (var parameter in item.Parameters) {
|
||||
|
||||
@@ -15,8 +15,7 @@ namespace Orchard.Events {
|
||||
private readonly IExceptionPolicy _exceptionPolicy;
|
||||
private static readonly ConcurrentDictionary<string, Tuple<ParameterInfo[], Func<IEventHandler, object[], object>>> _delegateCache = new ConcurrentDictionary<string, Tuple<ParameterInfo[], Func<IEventHandler, object[], object>>>();
|
||||
|
||||
public DefaultOrchardEventBus(IIndex<string, IEnumerable<Meta<IEventHandler>>> eventHandlers, IExceptionPolicy exceptionPolicy)
|
||||
{
|
||||
public DefaultOrchardEventBus(IIndex<string, IEnumerable<Meta<IEventHandler>>> eventHandlers, IExceptionPolicy exceptionPolicy) {
|
||||
_eventHandlers = eventHandlers;
|
||||
_exceptionPolicy = exceptionPolicy;
|
||||
T = NullLocalizer.Instance;
|
||||
@@ -52,7 +51,7 @@ namespace Orchard.Events {
|
||||
|
||||
private bool TryNotifyHandler(Meta<IEventHandler> eventHandler, string messageName, string interfaceName, string methodName, IDictionary<string, object> eventData, out IEnumerable returnValue) {
|
||||
try {
|
||||
return TryInvoke(eventHandler, interfaceName, methodName, eventData, out returnValue);
|
||||
return TryInvoke(eventHandler, messageName, interfaceName, methodName, eventData, out returnValue);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
if (!_exceptionPolicy.HandleException(this, exception)) {
|
||||
@@ -64,21 +63,19 @@ namespace Orchard.Events {
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryInvoke(Meta<IEventHandler> eventHandler, string interfaceName, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
|
||||
var matchingInterfaces = ((ILookup<string, Type>)eventHandler.Metadata["Interfaces"])[interfaceName];
|
||||
foreach (var interfaceType in matchingInterfaces) {
|
||||
return TryInvokeMethod(eventHandler.Value, interfaceType, methodName, arguments, out returnValue);
|
||||
}
|
||||
returnValue = null;
|
||||
return false;
|
||||
private static bool TryInvoke(Meta<IEventHandler> eventHandler, string messageName, string interfaceName, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
|
||||
var interfaces = (IDictionary<string, Type>)eventHandler.Metadata["Interfaces"];
|
||||
var matchingInterface = interfaces.Count == 1 ? interfaces.First().Value : interfaces[interfaceName];
|
||||
|
||||
return TryInvokeMethod(eventHandler.Value, matchingInterface, messageName, interfaceName, methodName, arguments, out returnValue);
|
||||
}
|
||||
|
||||
private static bool TryInvokeMethod(IEventHandler eventHandler, Type interfaceType, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
|
||||
var key = eventHandler.GetType().FullName + "_" + interfaceType.Name + "_" + methodName + "_" + String.Join("_", arguments.Keys);
|
||||
private static bool TryInvokeMethod(IEventHandler eventHandler, Type interfaceType, string messageName, string interfaceName, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
|
||||
var key = eventHandler.GetType().FullName + "_" + messageName + "_" + String.Join("_", arguments.Keys);
|
||||
var cachedDelegate = _delegateCache.GetOrAdd(key, k => {
|
||||
var method = GetMatchingMethod(eventHandler, interfaceType, methodName, arguments);
|
||||
return method != null
|
||||
? Tuple.Create(method.GetParameters(), DelegateHelper.CreateDelegate<IEventHandler>(interfaceType, method))
|
||||
return method != null
|
||||
? Tuple.Create(method.GetParameters(), DelegateHelper.CreateDelegate<IEventHandler>(eventHandler.GetType(), method))
|
||||
: null;
|
||||
});
|
||||
|
||||
@@ -89,9 +86,9 @@ namespace Orchard.Events {
|
||||
returnValue = result as IEnumerable;
|
||||
if (returnValue == null && result != null)
|
||||
returnValue = new[] { result };
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
returnValue = null;
|
||||
return false;
|
||||
}
|
||||
@@ -115,6 +112,11 @@ namespace Orchard.Events {
|
||||
}
|
||||
}
|
||||
|
||||
// treating common case separately
|
||||
if (candidates.Count == 1) {
|
||||
return candidates[0];
|
||||
}
|
||||
|
||||
if (candidates.Count != 0) {
|
||||
return candidates.OrderBy(x => x.GetParameters().Length).Last();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user