private static NotificationAsyncHandler BuildAsyncHandler(
Type targetType, Type invokePayloadType, MethodInfo method, FilterChain filterChain)
{
var isAsyncMethod = method.ReturnType.Name.StartsWith("Task");
var handler = isAsyncMethod
? RequestHandlerAsyncBuilder.Build(targetType, invokePayloadType, null, method)
: RequestHandlerSyncToAsyncBuilder.Build(targetType, invokePayloadType, null, method);
// TODO: Optimize this function when without async filter
return async delegate(object self, NotificationMessage notification)
{
var filterPerInstanceProvider = filterChain.PerInstanceFilterExists ? (IFilterPerInstanceProvider)self : null;
// Create PerRequest filters
IFilter[] filterPerRequests = null;
if (filterChain.PerInvokeFilterFactories.Length > 0)
{
filterPerRequests = new IFilter[filterChain.PerInvokeFilterFactories.Length];
for (var i = 0; i < filterChain.PerInvokeFilterFactories.Length; i++)
{
filterPerRequests[i] = filterChain.PerInvokeFilterFactories[i].CreateInstance(self, notification);
}
}
// Call PreFilters
var handled = false;
if (filterChain.PreFilterAccessors.Length > 0)
{
var context = new PreNotificationFilterContext
{
Actor = self,
Notification = notification
};
foreach (var filterAccessor in filterChain.PreFilterAccessors)
{
var filter = filterAccessor(filterPerInstanceProvider, filterPerRequests);
var preFilter = filter as IPreNotificationFilter;
if (preFilter != null)
preFilter.OnPreNotification(context);
else
await ((IPreNotificationAsyncFilter)filter).OnPreNotificationAsync(context);
}
handled = context.Handled;
}
// Call Handler
if (handled == false)
await handler(self, notification.InvokePayload);
// Call PostFilters
if (filterChain.PostFilterAccessors.Length > 0)
{
var context = new PostNotificationFilterContext
{
Actor = self,
Notification = notification,
Intercepted = handled
};
foreach (var filterAccessor in filterChain.PostFilterAccessors)
{
var filter = filterAccessor(filterPerInstanceProvider, filterPerRequests);
var postFilter = filter as IPostNotificationFilter;
if (postFilter != null)
postFilter.OnPostNotification(context);
else
await ((IPostNotificationAsyncFilter)filter).OnPostNotificationAsync(context);
}
}
};
}