-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added request handling interceptors and conventions for request/respo…
…nse types
- Loading branch information
1 parent
f15d182
commit 4c9e72c
Showing
35 changed files
with
1,890 additions
and
630 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Agatha.Common.Configuration | ||
{ | ||
public interface IRequestHandlerRegistry | ||
{ | ||
IEnumerable<Type> GetTypedRequestHandlers(); | ||
void Register(Type handlerType); | ||
} | ||
|
||
public class RequestHandlerRegistry : IRequestHandlerRegistry | ||
{ | ||
private readonly List<Type> requestHandlerTypes = new List<Type>(); | ||
|
||
public IEnumerable<Type> GetTypedRequestHandlers() | ||
{ | ||
return requestHandlerTypes; | ||
} | ||
|
||
public void Register(Type handlerType) | ||
{ | ||
requestHandlerTypes.Add(handlerType); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Agatha.Common.Configuration | ||
{ | ||
public interface IRequestTypeRegistry | ||
{ | ||
IEnumerable<Type> GetRegisteredRequestTypes(); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
Agatha.Common/Configuration/WcfKnownTypesBasedRequestTypeRegistry.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Agatha.Common.WCF; | ||
|
||
namespace Agatha.Common.Configuration | ||
{ | ||
public class WcfKnownTypesBasedRequestTypeRegistry : IRequestTypeRegistry | ||
{ | ||
public IEnumerable<Type> GetRegisteredRequestTypes() | ||
{ | ||
return KnownTypeProvider.GetKnownTypes(null); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Agatha.Common.Configuration; | ||
|
||
namespace Agatha.Common.Conventions | ||
{ | ||
public class BasicConventions : IConventions | ||
{ | ||
private readonly IDictionary<Type, Type> requestResponseMappings = new Dictionary<Type, Type>(); | ||
|
||
public BasicConventions(IRequestTypeRegistry configuration) | ||
{ | ||
BuildRequestReponseMappings(configuration.GetRegisteredRequestTypes()); | ||
} | ||
|
||
private void BuildRequestReponseMappings(IEnumerable<Type> requestTypes) | ||
{ | ||
foreach (var requestType in requestTypes.Where(t => t.Name.EndsWith("Request"))) | ||
{ | ||
requestResponseMappings.Add(requestType, DetermineResponseType(requestType)); | ||
} | ||
} | ||
|
||
private static Type DetermineResponseType(Type requestType) | ||
{ | ||
var requestTypeName = requestType.FullName; | ||
var responseTypeName = ReplaceRequestSuffix(requestTypeName); | ||
var reponseType = requestType.Assembly.GetType(responseTypeName); | ||
if (reponseType == null) throw new InvalidOperationException("Could not determine response type by convention for request of type " + requestTypeName); | ||
return reponseType; | ||
} | ||
|
||
private static string ReplaceRequestSuffix(string requestTypeName) | ||
{ | ||
var index = requestTypeName.LastIndexOf("Request"); | ||
return string.Concat(requestTypeName.Substring(0, index), "Response"); | ||
} | ||
|
||
public Type GetResponseTypeFor(Request request) | ||
{ | ||
if (request == null) throw new ArgumentNullException("request"); | ||
|
||
return requestResponseMappings[request.GetType()]; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using System; | ||
|
||
namespace Agatha.Common | ||
{ | ||
public interface IConventions | ||
{ | ||
Type GetResponseTypeFor(Request request); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System; | ||
using Agatha.Common.InversionOfControl; | ||
|
||
namespace Agatha.Common.Interceptors | ||
{ | ||
public abstract class ConventionBasedInterceptor : Disposable, IRequestHandlerInterceptor | ||
{ | ||
public abstract void BeforeHandlingRequest(RequestProcessingContext context); | ||
public abstract void AfterHandlingRequest(RequestProcessingContext context); | ||
protected IConventions Conventions { get; private set; } | ||
|
||
protected ConventionBasedInterceptor() | ||
{ | ||
Conventions = IoC.Container.Resolve<IConventions>(); | ||
} | ||
|
||
public Response CreateDefaultResponseFor(Request request) | ||
{ | ||
var responseType = Conventions.GetResponseTypeFor(request); | ||
return (Response)Activator.CreateInstance(responseType); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System; | ||
|
||
namespace Agatha.Common | ||
{ | ||
public interface IRequestHandlerInterceptor : IDisposable | ||
{ | ||
void BeforeHandlingRequest(RequestProcessingContext context); | ||
void AfterHandlingRequest(RequestProcessingContext context); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System; | ||
|
||
namespace Agatha.Common | ||
{ | ||
public class RequestProcessingContext | ||
{ | ||
public Request Request { get; private set; } | ||
public Response Response { get; private set; } | ||
|
||
public RequestProcessingContext(Request request) | ||
{ | ||
Request = request; | ||
} | ||
|
||
public void MarkAsProcessed(Response response) | ||
{ | ||
if (response == null) throw new ArgumentNullException("response"); | ||
Response = response; | ||
IsProcessed = true; | ||
} | ||
|
||
public bool IsProcessed { get; private set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
Agatha.ServiceLayer/Conventions/RequestHandlerBasedConventions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Agatha.Common; | ||
using Agatha.Common.Configuration; | ||
|
||
namespace Agatha.ServiceLayer.Conventions | ||
{ | ||
public class RequestHandlerBasedConventions : IConventions | ||
{ | ||
private readonly IDictionary<Type, Type> requestResponseMappings = new Dictionary<Type, Type>(); | ||
|
||
public RequestHandlerBasedConventions(IRequestHandlerRegistry configuration) | ||
{ | ||
BuildRequestReponseMappings(configuration.GetTypedRequestHandlers()); | ||
} | ||
|
||
private void BuildRequestReponseMappings(IEnumerable<Type> typedRequestHandlers) | ||
{ | ||
foreach (var handlerType in typedRequestHandlers) | ||
{ | ||
BuildRequestResponseMapping(handlerType); | ||
} | ||
} | ||
|
||
private void BuildRequestResponseMapping(Type handlerType) | ||
{ | ||
var handlerBase = FindHandlerBase(handlerType); | ||
if (handlerBase == null) return; | ||
|
||
var genericArguments = handlerBase.GetGenericArguments(); | ||
if (genericArguments.Length < 2) return; | ||
|
||
var requestType = genericArguments[0]; | ||
var responseType = genericArguments[1]; | ||
|
||
if (requestResponseMappings.ContainsKey(requestType)) | ||
return; | ||
|
||
requestResponseMappings.Add(requestType, responseType); | ||
} | ||
|
||
private Type FindHandlerBase(Type handlerType) | ||
{ | ||
while (!handlerType.IsGenericType && handlerType != typeof(object)) | ||
{ | ||
if(handlerType.BaseType.IsGenericType) | ||
{ | ||
return handlerType.BaseType; | ||
} | ||
handlerType = handlerType.BaseType; | ||
} | ||
return null; | ||
} | ||
|
||
public Type GetResponseTypeFor(Request request) | ||
{ | ||
if (request == null) throw new ArgumentNullException("request"); | ||
var requestType = request.GetType(); | ||
if(!requestResponseMappings.ContainsKey(requestType)) | ||
throw new Exception("No response type found by convention for request type " + requestType); | ||
|
||
return requestResponseMappings[requestType]; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.