Fixing the CodeGen issue for GetReturnValue and splitting the request and response message body

This commit is contained in:
shalabhs 2019-08-26 12:02:18 -07:00
parent f5674d2f23
commit f7d42f3092
24 changed files with 332 additions and 158 deletions

View File

@ -137,7 +137,7 @@ namespace Microsoft.Actions.Actors
var serializedHeader = this.serializersManager.GetHeaderSerializer()
.SerializeRequestHeader(remotingRequestRequestMessage.GetHeader());
var msgBodySeriaizer = this.serializersManager.GetMessageBodySerializer(interfaceId);
var msgBodySeriaizer = this.serializersManager.GetRequestMessageBodySerializer(interfaceId);
var serializedMsgBody = msgBodySeriaizer.Serialize(remotingRequestRequestMessage.GetBody());
// Send Request
@ -178,16 +178,15 @@ namespace Microsoft.Actions.Actors
}
// Get the http response message body content and extract out expected actor response message body
IActorMessageBody actorResponseMessageBody = null;
IActorResponseMessageBody actorResponseMessageBody = null;
if (retval != null && retval.Content != null)
{
var responseMessageBody = await retval.Content.ReadAsStreamAsync();
// Deserialize Actor Response Message Body
var responseBodySerializer = this.serializersManager.GetMessageBodySerializer(interfaceId);
var responseBodySerializer = this.serializersManager.GetResponseMessageBodySerializer(interfaceId);
actorResponseMessageBody =
responseBodySerializer.Deserialize(responseMessageBody);
actorResponseMessageBody = responseBodySerializer.Deserialize(responseMessageBody);
}
// TODO Either throw exception or return response body with null header and message body

View File

@ -42,10 +42,10 @@ namespace Microsoft.Actions.Actors.Builder
/// <param name="cancellationToken">The cancellation token that will be signaled if this operation is cancelled.</param>
/// <returns>A task that represents the outstanding asynchronous call to the implementation object.
/// The return value of the task contains the returned value from the invoked method.</returns>
public Task<IActorMessageBody> DispatchAsync(
public Task<IActorResponseMessageBody> DispatchAsync(
object objectImplementation,
int methodId,
IActorMessageBody requestBody,
IActorRequestMessageBody requestBody,
IActorMessageBodyFactory remotingMessageBodyFactory,
CancellationToken cancellationToken)
{
@ -68,7 +68,7 @@ namespace Microsoft.Actions.Actors.Builder
/// <param name="objectImplementation">The object implemented the remoted interface.</param>
/// <param name="methodId">Id of the method to which to dispatch the request to.</param>
/// <param name="requestMessageBody">The body of the request object that needs to be dispatched to the remoting implementation.</param>
public void Dispatch(object objectImplementation, int methodId, IActorMessageBody requestMessageBody)
public void Dispatch(object objectImplementation, int methodId, IActorRequestMessageBody requestMessageBody)
{
this.OnDispatch(methodId, objectImplementation, requestMessageBody);
}
@ -116,15 +116,15 @@ namespace Microsoft.Actions.Actors.Builder
/// <param name="methodId">MethodId of the remoting method.</param>
/// <param name="remotingMessageBodyFactory">MessageFactory for the remoting Interface.</param>
/// <param name="response">Response returned by remoting method.</param>
/// <returns>Remoting Response.</returns>
protected IActorMessageBody CreateResponseMessageBody(
/// <returns>Actor Response Message Body.</returns>
protected IActorResponseMessageBody CreateResponseMessageBody(
string interfaceName,
string methodName,
int methodId,
IActorMessageBodyFactory remotingMessageBodyFactory,
object response)
{
var msg = remotingMessageBodyFactory.CreateMessageBody(
var msg = remotingMessageBodyFactory.CreateResponseMessageBody(
interfaceName,
methodName,
this.CreateWrappedResponseBody(methodId, response));
@ -150,10 +150,10 @@ namespace Microsoft.Actions.Actors.Builder
/// A <see cref="System.Threading.Tasks.Task">Task</see> that represents outstanding operation.
/// The result of the task is the return value from the method.
/// </returns>
protected abstract Task<IActorMessageBody> OnDispatchAsync(
protected abstract Task<IActorResponseMessageBody> OnDispatchAsync(
int methodId,
object remotedObject,
IActorMessageBody requestBody,
IActorRequestMessageBody requestBody,
IActorMessageBodyFactory remotingMessageBodyFactory,
CancellationToken cancellationToken);
@ -164,7 +164,7 @@ namespace Microsoft.Actions.Actors.Builder
/// <param name="methodId">Id of the method.</param>
/// <param name="remotedObject">The remoted object instance.</param>
/// <param name="requestBody">Request body.</param>
protected abstract void OnDispatch(int methodId, object remotedObject, IActorMessageBody requestBody);
protected abstract void OnDispatch(int methodId, object remotedObject, IActorRequestMessageBody requestBody);
/// <summary>
/// Internal - used by Service remoting.
@ -178,7 +178,7 @@ namespace Microsoft.Actions.Actors.Builder
/// A <see cref="System.Threading.Tasks.Task">Task</see> that represents outstanding operation.
/// </returns>
/// <typeparam name="TRetVal">The response type for the remoting method.</typeparam>
protected Task<IActorMessageBody> ContinueWithResult<TRetVal>(
protected Task<IActorResponseMessageBody> ContinueWithResult<TRetVal>(
string interfaceName,
string methodName,
int methodId,
@ -210,13 +210,13 @@ namespace Microsoft.Actions.Actors.Builder
/// Internal - used by remoting
/// <summary>
/// This checks if we are wrapping remoting message or not.
/// This checks if we are wrapping actor message body or not.
/// </summary>
/// <param name="requestMessage">Remoting Request Message.</param>
/// <param name="requestMessageBody">Actor Request Message Body.</param>
/// <returns>true or false.</returns>
protected bool CheckIfItsWrappedRequest(IActorMessageBody requestMessage)
protected bool CheckIfItsWrappedRequest(IActorRequestMessageBody requestMessageBody)
{
if (requestMessage is WrappedMessage)
if (requestMessageBody is WrappedMessage)
{
return true;
}

View File

@ -37,7 +37,7 @@ namespace Microsoft.Actions.Actors.Builder
BindingFlags.Instance | BindingFlags.NonPublic,
null,
CallingConventions.Any,
new[] { typeof(int), typeof(int), typeof(string), typeof(IActorMessageBody), typeof(CancellationToken) },
new[] { typeof(int), typeof(int), typeof(string), typeof(IActorRequestMessageBody), typeof(CancellationToken) },
null);
this.checkIfitsWrapped = this.proxyBaseType.GetMethod(
@ -45,7 +45,7 @@ namespace Microsoft.Actions.Actors.Builder
BindingFlags.Instance | BindingFlags.NonPublic,
null,
CallingConventions.Any,
new[] { typeof(IActorMessageBody) },
new[] { typeof(IActorRequestMessageBody) },
null);
this.createMessage = this.proxyBaseType.GetMethod(
@ -61,7 +61,7 @@ namespace Microsoft.Actions.Actors.Builder
BindingFlags.Instance | BindingFlags.NonPublic,
null,
CallingConventions.Any,
new[] { typeof(int), typeof(int), typeof(IActorMessageBody) },
new[] { typeof(int), typeof(int), typeof(IActorRequestMessageBody) },
null);
this.continueWithResultMethodInfo = this.proxyBaseType.GetMethod(
@ -69,7 +69,7 @@ namespace Microsoft.Actions.Actors.Builder
BindingFlags.Instance | BindingFlags.NonPublic,
null,
CallingConventions.Any,
new[] { typeof(int), typeof(int), typeof(Task<IActorMessageBody>) },
new[] { typeof(int), typeof(int), typeof(Task<IActorResponseMessageBody>) },
null);
this.continueWithMethodInfo = this.proxyBaseType.GetMethod(
@ -326,7 +326,7 @@ namespace Microsoft.Actions.Actors.Builder
this.SetParameterIfNeeded(ilGen, requestMessage, parameterLength, parameters);
}
var objectTask = ilGen.DeclareLocal(typeof(Task<IActorMessageBody>));
var objectTask = ilGen.DeclareLocal(typeof(Task<IActorResponseMessageBody>));
// call the base InvokeAsync method
ilGen.Emit(OpCodes.Ldarg_0); // base
@ -466,7 +466,7 @@ namespace Microsoft.Actions.Actors.Builder
ilGen.Emit(OpCodes.Brfalse, elseLabel);
// if false ,Call SetParamater
var setMethod = typeof(IActorMessageBody).GetMethod("SetParameter");
var setMethod = typeof(IActorRequestMessageBody).GetMethod("SetParameter");
// Add to Dictionary
for (var i = 0; i < parameterLength; i++)
@ -495,7 +495,7 @@ namespace Microsoft.Actions.Actors.Builder
{
LocalBuilder requestMessage;
ilGen.Emit(OpCodes.Ldarg_0); // base
requestMessage = ilGen.DeclareLocal(typeof(IActorMessageBody));
requestMessage = ilGen.DeclareLocal(typeof(IActorRequestMessageBody));
ilGen.Emit(OpCodes.Ldstr, interfaceName);
ilGen.Emit(OpCodes.Ldstr, methodDescription.Name);
ilGen.Emit(OpCodes.Ldc_I4, parameterLength);
@ -526,7 +526,15 @@ namespace Microsoft.Actions.Actors.Builder
ilGen.Emit(OpCodes.Ldarg_3); // load responseBody object
ilGen.Emit(OpCodes.Castclass, responseBodyType); // cast it to responseBodyType
ilGen.Emit(OpCodes.Stloc, castedResponseBody); // store casted result to castedResponseBody local variable
ilGen.Emit(OpCodes.Ldloc, castedResponseBody);
var fieldInfo = responseBodyType.GetField(this.CodeBuilder.Names.RetVal);
ilGen.Emit(OpCodes.Ldloc, castedResponseBody);
ilGen.Emit(OpCodes.Ldfld, fieldInfo);
if (!fieldInfo.FieldType.GetTypeInfo().IsClass)
{
ilGen.Emit(OpCodes.Box, fieldInfo.FieldType);
}
ilGen.Emit(OpCodes.Ret);
}

View File

@ -38,7 +38,7 @@ namespace Microsoft.Actions.Actors.Builder
BindingFlags.Instance | BindingFlags.NonPublic,
null,
CallingConventions.Any,
new[] { typeof(IActorMessageBody) },
new[] { typeof(IActorRequestMessageBody) },
null);
}
@ -160,7 +160,7 @@ namespace Microsoft.Actions.Actors.Builder
typeof(void),
typeof(int), // methodid
typeof(object), // remoted object
typeof(IActorMessageBody)); // requestBody
typeof(IActorRequestMessageBody)); // requestBody
var ilGen = dispatchMethodImpl.GetILGenerator();
@ -205,7 +205,7 @@ namespace Microsoft.Actions.Actors.Builder
ilGen.Emit(OpCodes.Bne_Un, elseLabel);
// Check If its Wrapped , then call getparam
var requestBody = typeof(IActorMessageBody);
var requestBody = typeof(IActorRequestMessageBody);
// now invoke the method on the casted object
ilGen.Emit(OpCodes.Ldloc, castedObject);
@ -237,10 +237,10 @@ namespace Microsoft.Actions.Actors.Builder
var dispatchMethodImpl = CodeBuilderUtils.CreateProtectedMethodBuilder(
classBuilder,
"OnDispatchAsync",
typeof(Task<IActorMessageBody>),
typeof(Task<IActorResponseMessageBody>),
typeof(int), // methodid
typeof(object), // remoted object
typeof(IActorMessageBody), // requestBody
typeof(IActorRequestMessageBody), // requestBody
typeof(IActorMessageBodyFactory), // remotingmessageBodyFactory
typeof(CancellationToken)); // CancellationToken
@ -287,7 +287,7 @@ namespace Microsoft.Actions.Actors.Builder
ilGen.Emit(OpCodes.Bne_Un, elseLabel);
var invokeTask = ilGen.DeclareLocal(methodDescription.ReturnType);
var requestBody = typeof(IActorMessageBody);
var requestBody = typeof(IActorRequestMessageBody);
// now invoke the method on the casted object
ilGen.Emit(OpCodes.Ldloc, castedObject);

View File

@ -139,11 +139,11 @@ namespace Microsoft.Actions.Actors.Client
/// <param name="requestMsgBodyValue">Request Message Body Value.</param>
/// <param name="cancellationToken">Cancellation Token.</param>
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
protected async Task<IActorMessageBody> InvokeAsync(
protected async Task<IActorResponseMessageBody> InvokeAsync(
int interfaceId,
int methodId,
string methodName,
IActorMessageBody requestMsgBodyValue,
IActorRequestMessageBody requestMsgBodyValue,
CancellationToken cancellationToken)
{
var headers = new ActorRequestMessageHeader
@ -168,20 +168,20 @@ namespace Microsoft.Actions.Actors.Client
}
/// <summary>
/// Creates the Remoting request message Body.
/// Creates the Actor request message Body.
/// </summary>
/// <param name="interfaceName">Full Name of the service interface for which this call is invoked.</param>
/// <param name="methodName">Method Name of the service interface for which this call is invoked.</param>
/// <param name="parameterCount">Number of Parameters in the service interface Method.</param>
/// <param name="wrappedRequest">Wrapped Request Object.</param>
/// <returns>A request message body for V2 remoting stack.</returns>
protected IActorMessageBody CreateRequestMessageBody(
/// <returns>A request message body.</returns>
protected IActorRequestMessageBody CreateRequestMessageBody(
string interfaceName,
string methodName,
int parameterCount,
object wrappedRequest)
{
return this.ActorMessageBodyFactory.CreateMessageBody(interfaceName, methodName, wrappedRequest, parameterCount);
return this.ActorMessageBodyFactory.CreateRequestMessageBody(interfaceName, methodName, parameterCount, wrappedRequest);
}
/// <summary>
@ -205,7 +205,7 @@ namespace Microsoft.Actions.Actors.Client
/// <returns>Return value of method call as <see cref="object"/>.</returns>
protected virtual object GetReturnValue(int interfaceId, int methodId, object responseBody)
{
return null;
return Task.CompletedTask;
}
/// <summary>
@ -220,29 +220,31 @@ namespace Microsoft.Actions.Actors.Client
protected async Task<TRetval> ContinueWithResult<TRetval>(
int interfaceId,
int methodId,
Task<IActorMessageBody> task)
Task<IActorResponseMessageBody> task)
{
var responseBody = await task;
var wrappedMessage = responseBody as WrappedMessage;
if (wrappedMessage != null)
{
return (TRetval)this.GetReturnValue(
var obj = this.GetReturnValue(
interfaceId,
methodId,
wrappedMessage.Value);
return (TRetval)obj;
}
return (TRetval)responseBody.Get(typeof(TRetval));
}
/// <summary>
/// This check if we are wrapping remoting message or not.
/// This check if we are wrapping actor message or not.
/// </summary>
/// <param name="requestMessage">Remoting Request Message.</param>
/// <param name="requestMessageBody">Actor Request Message Body.</param>
/// <returns>true or false. </returns>
protected bool CheckIfItsWrappedRequest(IActorMessageBody requestMessage)
protected bool CheckIfItsWrappedRequest(IActorRequestMessageBody requestMessageBody)
{
if (requestMessage is WrappedMessage)
if (requestMessageBody is WrappedMessage)
{
return true;
}

View File

@ -42,25 +42,53 @@ namespace Microsoft.Actions.Actors.Communication
}
/// <summary>
/// Creates IActorMessageBodySerializer for a serviceInterface using Wrapped Message DataContract implementation.
/// Creates IActorRequestMessageBodySerializer for a serviceInterface using Wrapped Message DataContract implementation.
/// </summary>
/// <param name="serviceInterfaceType">The remoted service interface.</param>
/// <param name="methodParameterTypes">The union of parameter types of all of the methods of the specified interface.</param>
/// <param name="wrappedMessageTypes">Wrapped Request Types for all Methods.</param>
/// <param name="methodRequestParameterTypes">The union of parameter types of all of the methods of the specified interface.</param>
/// <param name="wrappedRequestMessageTypes">Wrapped Request Types for all Methods.</param>
/// <returns>
/// An instance of the <see cref="IActorMessageBodySerializer" /> that can serialize the service
/// remoting request message body to a messaging body for transferring over the transport.
/// An instance of the <see cref="IActorRequestMessageBodySerializer" /> that can serialize the service
/// actor request message body to a messaging body for transferring over the transport.
/// </returns>
public IActorMessageBodySerializer CreateMessageBodySerializer(
public IActorRequestMessageBodySerializer CreateRequestMessageBodySerializer(
Type serviceInterfaceType,
IEnumerable<Type> methodParameterTypes,
IEnumerable<Type> wrappedMessageTypes = null)
{
IEnumerable<Type> methodRequestParameterTypes,
IEnumerable<Type> wrappedRequestMessageTypes = null)
{
var knownTypes = new List<Type>(DefaultKnownTypes);
knownTypes.AddRange(wrappedRequestMessageTypes);
DataContractSerializer serializer = this.CreateMessageBodyDataContractSerializer(
typeof(WrappedMessageBody),
wrappedMessageTypes);
knownTypes);
return new MemoryStreamMessageBodySerializer(this, serializer);
return new MemoryStreamMessageBodySerializer<WrappedMessageBody, WrappedMessageBody>(this, serializer);
}
/// <summary>
/// Creates IActorResponseMessageBodySerializer for a serviceInterface using Wrapped Message DataContract implementation.
/// </summary>
/// <param name="serviceInterfaceType">The remoted service interface.</param>
/// <param name="methodReturnTypes">The return types of all of the methods of the specified interface.</param>
/// <param name="wrappedResponseMessageTypes">Wrapped Response Types for all remoting methods.</param>
/// <returns>
/// An instance of the <see cref="IActorResponseMessageBodySerializer" /> that can serialize the service
/// actor response message body to a messaging body for transferring over the transport.
/// </returns>
public IActorResponseMessageBodySerializer CreateResponseMessageBodySerializer(
Type serviceInterfaceType,
IEnumerable<Type> methodReturnTypes,
IEnumerable<Type> wrappedResponseMessageTypes = null)
{
var knownTypes = new List<Type>(DefaultKnownTypes);
knownTypes.AddRange(wrappedResponseMessageTypes);
DataContractSerializer serializer = this.CreateMessageBodyDataContractSerializer(
typeof(WrappedMessageBody),
knownTypes);
return new MemoryStreamMessageBodySerializer<WrappedMessageBody, WrappedMessageBody>(this, serializer);
}
/// <summary>
@ -74,7 +102,7 @@ namespace Microsoft.Actions.Actors.Communication
/// </returns>
internal XmlDictionaryWriter CreateXmlDictionaryWriter(Stream outputStream)
{
return XmlDictionaryWriter.CreateBinaryWriter(outputStream);
return XmlDictionaryWriter.CreateTextWriter(outputStream);
}
/// <summary>
@ -88,7 +116,7 @@ namespace Microsoft.Actions.Actors.Communication
/// </returns>
internal XmlDictionaryReader CreateXmlDictionaryReader(Stream inputStream)
{
return XmlDictionaryReader.CreateBinaryReader(inputStream, XmlDictionaryReaderQuotas.Max);
return XmlDictionaryReader.CreateTextReader(inputStream, XmlDictionaryReaderQuotas.Max);
}
/// <summary>
@ -106,26 +134,22 @@ namespace Microsoft.Actions.Actors.Communication
new DataContractSerializerSettings()
{
MaxItemsInObjectGraph = int.MaxValue,
KnownTypes = AddDefaultKnownTypes(knownTypes),
KnownTypes = knownTypes,
});
serializer.SetSerializationSurrogateProvider(new ActorDataContractSurrogate());
return serializer;
}
private static IEnumerable<Type> AddDefaultKnownTypes(IEnumerable<Type> knownTypes)
{
var types = new List<Type>(knownTypes);
types.AddRange(DefaultKnownTypes);
return types;
}
/// <summary>
/// Default serializer for service remoting request and response message body that uses the
/// memory stream to create outgoing message buffers.
/// </summary>
private class MemoryStreamMessageBodySerializer :
IActorMessageBodySerializer
private class MemoryStreamMessageBodySerializer<TRequest, TResponse> :
IActorRequestMessageBodySerializer,
IActorResponseMessageBodySerializer
where TRequest : IActorRequestMessageBody
where TResponse : IActorResponseMessageBody
{
private readonly ActorMessageBodyDataContractSerializationProvider serializationProvider;
private readonly DataContractSerializer serializer;
@ -138,10 +162,10 @@ namespace Microsoft.Actions.Actors.Communication
this.serializer = serializer;
}
byte[] IActorMessageBodySerializer.Serialize(
IActorMessageBody serviceRemotingRequestMessageBody)
byte[] IActorRequestMessageBodySerializer.Serialize(
IActorRequestMessageBody actorRequestMessageBody)
{
if (serviceRemotingRequestMessageBody == null)
if (actorRequestMessageBody == null)
{
return null;
}
@ -150,7 +174,7 @@ namespace Microsoft.Actions.Actors.Communication
{
using (var writer = this.CreateXmlDictionaryWriter(stream))
{
this.serializer.WriteObject(writer, serviceRemotingRequestMessageBody);
this.serializer.WriteObject(writer, actorRequestMessageBody);
writer.Flush();
return stream.ToArray();
@ -158,7 +182,7 @@ namespace Microsoft.Actions.Actors.Communication
}
}
IActorMessageBody IActorMessageBodySerializer.Deserialize(
IActorRequestMessageBody IActorRequestMessageBodySerializer.Deserialize(
Stream messageBody)
{
if (messageBody == null)
@ -170,7 +194,42 @@ namespace Microsoft.Actions.Actors.Communication
{
using (var reader = this.CreateXmlDictionaryReader(stream))
{
return (WrappedMessageBody)this.serializer.ReadObject(reader);
return (TRequest)this.serializer.ReadObject(reader);
}
}
}
byte[] IActorResponseMessageBodySerializer.Serialize(IActorResponseMessageBody actorResponseMessageBody)
{
if (actorResponseMessageBody == null)
{
return null;
}
using (var stream = new MemoryStream())
{
using (var writer = this.CreateXmlDictionaryWriter(stream))
{
this.serializer.WriteObject(writer, actorResponseMessageBody);
writer.Flush();
return stream.ToArray();
}
}
}
IActorResponseMessageBody IActorResponseMessageBodySerializer.Deserialize(Stream messageBody)
{
if (messageBody == null)
{
return null;
}
using (var stream = new DisposableStream(messageBody))
{
using (var reader = this.CreateXmlDictionaryReader(stream))
{
return (TResponse)this.serializer.ReadObject(reader);
}
}
}

View File

@ -44,9 +44,14 @@ namespace Microsoft.Actions.Actors.Communication
return this.headerSerializer;
}
public IActorMessageBodySerializer GetMessageBodySerializer(int interfaceId)
public IActorRequestMessageBodySerializer GetRequestMessageBodySerializer(int interfaceId)
{
return this.cachedBodySerializers.GetOrAdd(interfaceId, this.CreateSerializers).MessageBodySerializer;
return this.cachedBodySerializers.GetOrAdd(interfaceId, this.CreateSerializers).RequestMessageBodySerializer;
}
public IActorResponseMessageBodySerializer GetResponseMessageBodySerializer(int interfaceId)
{
return this.cachedBodySerializers.GetOrAdd(interfaceId, this.CreateSerializers).ResponseMessageBodySerializer;
}
internal CacheEntry CreateSerializers(int interfaceId)
@ -63,7 +68,8 @@ namespace Microsoft.Actions.Actors.Communication
var responseBodyTypes = interfaceDetails.ResponseKnownTypes;
return new CacheEntry(
this.serializationProvider.CreateMessageBodySerializer(serviceInterfaceType, requestBodyTypes, interfaceDetails.RequestWrappedKnownTypes));
this.serializationProvider.CreateRequestMessageBodySerializer(serviceInterfaceType, requestBodyTypes, interfaceDetails.RequestWrappedKnownTypes),
this.serializationProvider.CreateResponseMessageBodySerializer(serviceInterfaceType, responseBodyTypes, interfaceDetails.ResponseWrappedKnownTypes));
}
internal InterfaceDetails GetInterfaceDetails(int interfaceId)

View File

@ -8,9 +8,9 @@ namespace Microsoft.Actions.Actors.Communication
internal class ActorRequestMessage : IActorRequestMessage
{
private readonly IActorRequestMessageHeader header;
private readonly IActorMessageBody msgBody;
private readonly IActorRequestMessageBody msgBody;
public ActorRequestMessage(IActorRequestMessageHeader header, IActorMessageBody msgBody)
public ActorRequestMessage(IActorRequestMessageHeader header, IActorRequestMessageBody msgBody)
{
this.header = header;
this.msgBody = msgBody;
@ -21,7 +21,7 @@ namespace Microsoft.Actions.Actors.Communication
return this.header;
}
public IActorMessageBody GetBody()
public IActorRequestMessageBody GetBody()
{
return this.msgBody;
}

View File

@ -10,15 +10,12 @@ namespace Microsoft.Actions.Actors.Communication
using System.Runtime.Serialization;
[DataContract(Name = "msgBody", Namespace = Constants.Namespace)]
internal class ActorMessageBody : IActorMessageBody
internal class ActorRequestMessageBody : IActorRequestMessageBody
{
[DataMember]
private Dictionary<string, object> parameters;
[DataMember]
private object response;
public ActorMessageBody(int parameterInfos)
public ActorRequestMessageBody(int parameterInfos)
{
this.parameters = new Dictionary<string, object>(parameterInfos);
}
@ -32,15 +29,5 @@ namespace Microsoft.Actions.Actors.Communication
{
return this.parameters[paramName];
}
public void Set(object response)
{
this.response = response;
}
public object Get(Type paramType)
{
return this.response;
}
}
}

View File

@ -8,11 +8,11 @@ namespace Microsoft.Actions.Actors.Communication
internal class ActorResponseMessage : IActorResponseMessage
{
private readonly IActorResponseMessageHeader header;
private readonly IActorMessageBody msgBody;
private readonly IActorResponseMessageBody msgBody;
public ActorResponseMessage(
IActorResponseMessageHeader header,
IActorMessageBody msgBody)
IActorResponseMessageBody msgBody)
{
this.header = header;
this.msgBody = msgBody;
@ -23,7 +23,7 @@ namespace Microsoft.Actions.Actors.Communication
return this.header;
}
public IActorMessageBody GetBody()
public IActorResponseMessageBody GetBody()
{
return this.msgBody;
}

View File

@ -0,0 +1,27 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------
namespace Microsoft.Actions.Actors.Communication
{
using System;
using System.Runtime.Serialization;
[DataContract(Name = "msgResponse", Namespace = Constants.Namespace)]
internal class ActorResponseMessageBody : IActorResponseMessageBody
{
[DataMember]
private object response;
public void Set(object response)
{
this.response = response;
}
public object Get(Type paramType)
{
return this.response;
}
}
}

View File

@ -8,11 +8,15 @@ namespace Microsoft.Actions.Actors.Communication
internal class CacheEntry
{
public CacheEntry(
IActorMessageBodySerializer messageBodySerializer)
IActorRequestMessageBodySerializer requestBodySerializer,
IActorResponseMessageBodySerializer responseBodySerializer)
{
this.MessageBodySerializer = messageBodySerializer;
this.RequestMessageBodySerializer = requestBodySerializer;
this.ResponseMessageBodySerializer = responseBodySerializer;
}
public IActorMessageBodySerializer MessageBodySerializer { get; }
public IActorRequestMessageBodySerializer RequestMessageBodySerializer { get; }
public IActorResponseMessageBodySerializer ResponseMessageBodySerializer { get; }
}
}

View File

@ -7,9 +7,14 @@ namespace Microsoft.Actions.Actors.Communication
{
internal class DataContractMessageFactory : IActorMessageBodyFactory
{
public IActorMessageBody CreateMessageBody(string interfaceName, string methodName, object wrappedMessageObject, int numberOfParameters = 0)
public IActorRequestMessageBody CreateRequestMessageBody(string interfaceName, string methodName, int numberOfParameters, object wrappedRequestObject)
{
return new ActorMessageBody(numberOfParameters);
return new ActorRequestMessageBody(numberOfParameters);
}
public IActorResponseMessageBody CreateResponseMessageBody(string interfaceName, string methodName, object wrappedResponseObject)
{
return new ActorResponseMessageBody();
}
}
}

View File

@ -6,18 +6,27 @@
namespace Microsoft.Actions.Actors.Communication
{
/// <summary>
/// Defines the interface that must be implemented for providing factory for creating remoting request body and response body objects.
/// Defines the interface that must be implemented for providing factory for creating actor request body and response body objects.
/// </summary>
public interface IActorMessageBodyFactory
{
/// <summary>
/// Creates a remoting request message body.
/// Creates a actor request message body.
/// </summary>
/// <param name="interfaceName"> This is FullName for the service interface for which request body is being constructed.</param>
/// <param name="methodName">MethodName for the service interface for which request will be sent to.</param>
/// <param name="wrappedMessageObject">Wrapped Request Object.</param>
/// <param name="numberOfParameters">Number of Parameters in that Method.</param>
/// <returns>IRequestMessageBody.</returns>
IActorMessageBody CreateMessageBody(string interfaceName, string methodName, object wrappedMessageObject, int numberOfParameters = 0);
/// <param name="wrappedRequestObject">Wrapped Request Object.</param>
/// <returns>IActorRequestMessageBody.</returns>
IActorRequestMessageBody CreateRequestMessageBody(string interfaceName, string methodName, int numberOfParameters, object wrappedRequestObject);
/// <summary>
/// Creates a actor response message body.
/// </summary>
/// <param name="interfaceName"> This is FullName for the service interface for which request body is being constructed.</param>
/// <param name="methodName">MethodName for the service interface for which request will be sent to.</param>
/// <param name="wrappedResponseObject">Wrapped Response Object.</param>
/// <returns>IActorResponseMessageBody.</returns>
IActorResponseMessageBody CreateResponseMessageBody(string interfaceName, string methodName, object wrappedResponseObject);
}
}

View File

@ -19,19 +19,34 @@ namespace Microsoft.Actions.Actors.Communication
/// <returns>A custom <see cref="IActorMessageBodyFactory"/> that can be used for creating remoting request and response message bodies.</returns>
IActorMessageBodyFactory CreateMessageBodyFactory();
/// <summary>
/// Creates a serializer that can serialize and deserialize the remoting request message bodies for the specified service interface.
/// </summary>
/// <param name="serviceInterfaceType">User service interface.</param>
/// <param name="requestWrappedTypes">Wrapped Request object Types for all method.</param>
/// <param name="requestBodyTypes">Parameters for all the methods in the serviceInterfaceType.</param>
/// <returns>
/// An <see cref="IActorMessageBodySerializer"/> that can serialize and deserialize
/// the remoting request message bodies created by the custom service remoting message body factory.
/// </returns>
IActorMessageBodySerializer CreateMessageBodySerializer(
Type serviceInterfaceType,
IEnumerable<Type> requestWrappedTypes,
IEnumerable<Type> requestBodyTypes = null);
/// <summary>
/// Creates IActorRequestMessageBodySerializer for a serviceInterface using Wrapped Message DataContract implementation.
/// </summary>
/// <param name="serviceInterfaceType">The remoted service interface.</param>
/// <param name="methodRequestParameterTypes">The union of parameter types of all of the methods of the specified interface.</param>
/// <param name="wrappedRequestMessageTypes">Wrapped Request Types for all Methods.</param>
/// <returns>
/// An instance of the <see cref="IActorRequestMessageBodySerializer" /> that can serialize the service
/// actor request message body to a messaging body for transferring over the transport.
/// </returns>
IActorRequestMessageBodySerializer CreateRequestMessageBodySerializer(
Type serviceInterfaceType,
IEnumerable<Type> methodRequestParameterTypes,
IEnumerable<Type> wrappedRequestMessageTypes = null);
/// <summary>
/// Creates IActorResponseMessageBodySerializer for a serviceInterface using Wrapped Message DataContract implementation.
/// </summary>
/// <param name="serviceInterfaceType">The remoted service interface.</param>
/// <param name="methodReturnTypes">The return types of all of the methods of the specified interface.</param>
/// <param name="wrappedResponseMessageTypes">Wrapped Response Types for all remoting methods.</param>
/// <returns>
/// An instance of the <see cref="IActorResponseMessageBodySerializer" /> that can serialize the service
/// actor response message body to a messaging body for transferring over the transport.
/// </returns>
IActorResponseMessageBodySerializer CreateResponseMessageBodySerializer(
Type serviceInterfaceType,
IEnumerable<Type> methodReturnTypes,
IEnumerable<Type> wrappedResponseMessageTypes = null);
}
}

View File

@ -6,19 +6,19 @@
namespace Microsoft.Actions.Actors.Communication
{
/// <summary>
/// Defines the interface that must be implemented for create Remoting Request Message.
/// Defines the interface that must be implemented for create Actor Request Message.
/// </summary>
public interface IActorRequestMessage
{
/// <summary>
/// Gets the Remoting Request Message Header.
/// Gets the Actor Request Message Header.
/// </summary>
/// <returns>IServiceRemotingRequestMessageHeader.</returns>
/// <returns>IActorRequestMessageHeader.</returns>
IActorRequestMessageHeader GetHeader();
/// <summary>
/// Gets the Remoting Request Message Body.</summary>
/// <returns>IServiceRemotingRequestMessageBody.</returns>
IActorMessageBody GetBody();
/// Gets the Actor Request Message Body.</summary>
/// <returns>IActorRequestMessageBody.</returns>
IActorRequestMessageBody GetBody();
}
}

View File

@ -11,7 +11,7 @@ namespace Microsoft.Actions.Actors.Communication
/// Defines the interface that must be implemented to provide Request Message Body for remoting requests .
/// This contains all the parameters remoting method has.
/// </summary>
public interface IActorMessageBody
public interface IActorRequestMessageBody
{
/// <summary>
/// This Api gets called to set remoting method parameters before serializing/dispatching the request.
@ -29,18 +29,5 @@ namespace Microsoft.Actions.Actors.Communication
/// <param name="paramType">Parameter Type.</param>
/// <returns>The parameter that is at the specified position and has the specified name.</returns>
object GetParameter(int position, string parameName, Type paramType);
/// <summary>
/// Sets the response of a remoting Method in a remoting response Body.
/// </summary>
/// <param name="response">Remoting Method Response.</param>
void Set(object response);
/// <summary>
/// Gets the response of a remoting Method from a remoting response body before sending it to Client.
/// </summary>
/// <param name="paramType"> Return Type of a Remoting Method.</param>
/// <returns>Remoting Method Response.</returns>
object Get(Type paramType);
}
}

View File

@ -10,20 +10,20 @@ namespace Microsoft.Actions.Actors.Communication
/// <summary>
/// Defines the interface that must be implemented to provide a serializer/deserializer for remoting request message body.
/// </summary>
public interface IActorMessageBodySerializer
public interface IActorRequestMessageBodySerializer
{
/// <summary>
/// Serialize the remoting request body object to a message body that can be sent over the wire.
/// </summary>
/// <param name="serviceRemotingRequestMessageBody">Remoting request message body object.</param>
/// <param name="actorRequestMessageBody">Actor request message body object.</param>
/// <returns>Serialized message body.</returns>
byte[] Serialize(IActorMessageBody serviceRemotingRequestMessageBody);
byte[] Serialize(IActorRequestMessageBody actorRequestMessageBody);
/// <summary>
/// Deserializes an incoming message body to remoting request body object.
/// Deserializes an incoming message body to actor request body object.
/// </summary>
/// <param name="messageBody">Serialized message body.</param>
/// <returns>Deserialized remoting request message body object.</returns>
IActorMessageBody Deserialize(Stream messageBody);
IActorRequestMessageBody Deserialize(Stream messageBody);
}
}

View File

@ -6,7 +6,7 @@
namespace Microsoft.Actions.Actors.Communication
{
/// <summary>
/// Defines an interface that must be implemented to provide a remoting response message for remoting Api.
/// Defines an interface that must be implemented to provide a actor response message for remoting Api.
/// </summary>
public interface IActorResponseMessage
{
@ -20,6 +20,6 @@ namespace Microsoft.Actions.Actors.Communication
/// Gets the body of the response message.
/// </summary>
/// <returns>The body of this response message.</returns>
IActorMessageBody GetBody();
IActorResponseMessageBody GetBody();
}
}

View File

@ -0,0 +1,29 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------
namespace Microsoft.Actions.Actors.Communication
{
using System;
/// <summary>
/// Defines the interface that must be implemented to provide Request Message Body for remoting requests .
/// This contains all the parameters remoting method has.
/// </summary>
public interface IActorResponseMessageBody
{
/// <summary>
/// Sets the response of a remoting Method in a remoting response Body.
/// </summary>
/// <param name="response">Remoting Method Response.</param>
void Set(object response);
/// <summary>
/// Gets the response of a remoting Method from a remoting response body before sending it to Client.
/// </summary>
/// <param name="paramType"> Return Type of a Remoting Method.</param>
/// <returns>Remoting Method Response.</returns>
object Get(Type paramType);
}
}

View File

@ -0,0 +1,29 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------
namespace Microsoft.Actions.Actors.Communication
{
using System.IO;
/// <summary>
/// Defines the interface that must be implemented to provide a serializer/deserializer for actor response message body.
/// </summary>
public interface IActorResponseMessageBodySerializer
{
/// <summary>
/// Serialize the actor response body object to a message body that can be sent over the wire.
/// </summary>
/// <param name="actorResponseMessageBody">Actor request message body object.</param>
/// <returns>Serialized message body.</returns>
byte[] Serialize(IActorResponseMessageBody actorResponseMessageBody);
/// <summary>
/// Deserializes an incoming message body to remoting response body object.
/// </summary>
/// <param name="messageBody">Serialized message body.</param>
/// <returns>Deserialized actor response message body object.</returns>
IActorResponseMessageBody Deserialize(Stream messageBody);
}
}

View File

@ -9,7 +9,7 @@ using Microsoft.Actions.Actors;
using Microsoft.Actions.Actors.Communication;
[DataContract(Name = "WrappedMsgBody", Namespace = Constants.Namespace)]
internal class WrappedMessageBody : WrappedMessage, IActorMessageBody
internal class WrappedMessageBody : WrappedMessage, IActorRequestMessageBody, IActorResponseMessageBody
{
public void SetParameter(
int position,

View File

@ -7,11 +7,19 @@ using Microsoft.Actions.Actors.Communication;
internal class WrappedRequestMessageFactory : IActorMessageBodyFactory
{
public IActorMessageBody CreateMessageBody(string interfaceName, string methodName, object wrappedMessageObject, int numberOfParameters = 0)
public IActorRequestMessageBody CreateRequestMessageBody(string interfaceName, string methodName, int numberOfParameters, object wrappedRequestObject)
{
return new WrappedMessageBody()
{
Value = wrappedMessageObject,
Value = wrappedRequestObject,
};
}
public IActorResponseMessageBody CreateResponseMessageBody(string interfaceName, string methodName, object wrappedResponseObject)
{
return new WrappedMessageBody()
{
Value = wrappedResponseObject,
};
}
}

View File

@ -53,7 +53,7 @@ namespace Microsoft.Actions.Actors.Runtime
var interfaceId = actorMessageHeader.InterfaceId;
// Get the deserialized Body.
var msgBodySerializer = this.serializersManager.GetMessageBodySerializer(actorMessageHeader.InterfaceId);
var msgBodySerializer = this.serializersManager.GetRequestMessageBodySerializer(actorMessageHeader.InterfaceId);
var actorMessageBody = msgBodySerializer.Deserialize(data);
// Call the method on the method dispatcher using the Func below.
@ -62,12 +62,12 @@ namespace Microsoft.Actions.Actors.Runtime
// Create a Func to be invoked by common method.
async Task<Tuple<string, string>> RequestFunc(Actor actor, CancellationToken ct)
{
IActorMessageBody responseMsgBody = null;
IActorResponseMessageBody responseMsgBody = null;
var actorResponseMessageHeader = new ActorResponseMessageHeader();
try
{
responseMsgBody = (IActorMessageBody)await methodDispatcher.DispatchAsync(
responseMsgBody = (IActorResponseMessageBody)await methodDispatcher.DispatchAsync(
actor,
actorMessageHeader.MethodId,
actorMessageBody,
@ -211,7 +211,7 @@ namespace Microsoft.Actions.Actors.Runtime
return this.ActorTypeInfo.ActorFactory.Invoke(actorId);
}
private Tuple<string, string> CreateResponseMessage(IActorResponseMessageHeader header, IActorMessageBody msgBody, int interfaceId)
private Tuple<string, string> CreateResponseMessage(IActorResponseMessageHeader header, IActorResponseMessageBody msgBody, int interfaceId)
{
string responseHeader = string.Empty;
if (header != null)
@ -227,7 +227,7 @@ namespace Microsoft.Actions.Actors.Runtime
string responseMsgBody = string.Empty;
if (msgBody != null)
{
var responseSerializer = this.serializersManager.GetMessageBodySerializer(interfaceId);
var responseSerializer = this.serializersManager.GetResponseMessageBodySerializer(interfaceId);
var responseMsgBodyBytes = responseSerializer.Serialize(msgBody);
responseMsgBody = Encoding.UTF8.GetString(responseMsgBodyBytes, 0, responseMsgBodyBytes.Length);