由于Orlans不支持Linq 表达式参数,所以只能把Linq 表达式参数转换为JObject类型的参数
有关Orleans自定义序列化参数
http://dotnet.github.io/orleans/Documentation/Advanced-Concepts/Serialization.html
序列化JObject类型的参数代码如下:
using Newtonsoft.Json.Linq;
using Orleans.Runtime;
using Orleans.Serialization;
using System;
namespace NoobOrleans.Core
{
///
/// An implementation of IExternalSerializer for usage with linq types.
///
public class JsonSerializer : IExternalSerializer
{
//增加自定义的处理类
private static readonly Type JsonType = typeof(JObject);
protected Logger logger;
public JsonSerializer()
{
}
///
/// Initializes the external serializer
///
/// The logger to use to capture any serialization events
public void Initialize(Logger logger)
{
this.logger = logger;
}
///
/// Informs the serialization manager whether this serializer supports the type for serialization.
///
/// The type of the item to be serialized
/// A value indicating whether the item can be serialized.
public bool IsSupportedType(Type itemType)
{
if (JsonType.IsAssignableFrom(itemType))
{
return true;
}
return false;
}
///
/// Tries to create a copy of source.
///
/// The item to create a copy of
/// The context in which the object is being copied.
/// The copy
public virtual object DeepCopy(object source, ICopyContext context)
{
if (source == null)
{
return null;
}
//Expression expression = source as Expression;
//if (expression == null)
//{
// throw new ArgumentException("The provided item for serialization in not an instance of " + typeof(Expression), "item");
//}
//byte[] outBytes = serializer.SerializeBinary(expression);
//object target = serializer.DeserializeBinary(outBytes);//
//return target;
return source;
}
///
/// Tries to serialize an item.
///
/// The instance of the object being serialized
/// The context in which the object is being serialized.
/// The type that the deserializer will expect
public virtual void Serialize(object item, ISerializationContext context, Type expectedType)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var writer = context.StreamWriter;
if (item == null)
{
writer.WriteNull();
return;
}
Type type = item.GetType();
var typeHandle = type.TypeHandle;
if (logger != null)
{
logger.Verbose("JsonSerializer,Serialize,expectedType:" + expectedType + ",item.type:" + type + ",item.TypeHandle:" + typeHandle);
}
var input = item as JObject;
string str = input.ToString();
if (logger != null)
{
logger.Verbose("JsonSerializer,JObject.ToString():" + str);
}
context.SerializationManager.Serialize(str, context.StreamWriter);
}
///
/// Tries to deserialize an item.
///
/// The context in which the object is being deserialized.
/// The type that should be deserialized
/// The deserialized object
public virtual object Deserialize(Type expectedType, IDeserializationContext context)
{
if (expectedType == null)
{
throw new ArgumentNullException(nameof(expectedType));
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var typeHandle = expectedType.TypeHandle;
if (logger != null)
{
logger.Verbose("JsonSerializer,Deserialize,expectedType:" + expectedType + ",expectedType.TypeHandle:" + expectedType.TypeHandle);
}
var str = (string)context.SerializationManager.Deserialize(typeof(string), context.StreamReader);
if (logger != null)
{
logger.Verbose("JsonSerializer,Deserialize,str:" + str);
}
return JObject.Parse(str);
}
}
}
Linq表达式转换为JObject对象代码如下
注意需要引用第三方“ Serialize.Linq.dll”库
对应的Github地址如下:
https://github.com/esskar/Serialize.Linq
using Newtonsoft.Json.Linq;
using Orchard.Data;
using Serialize.Linq.Serializers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace Orchard.Orleans
{
///
///
///
public static partial class ExpressionExtension
{
///
/// Predicate JObject
///
///
///
///
public static JObject ToJObject(this Expression> predicate) where TEntity : class
{
string predicateJson = JsonSerializerUtils.SerializeText(predicate);
if (string.IsNullOrEmpty(predicateJson))
{
return null;
}
return JObject.Parse(predicateJson);
}
///
///
///
///
///
///
///
public static JObject ToJObject(this Expression> expression) where TEntity : class
{
string predicateJson = JsonSerializerUtils.SerializeText(expression);
if (string.IsNullOrEmpty(predicateJson))
{
return null;
}
return JObject.Parse(predicateJson);
}
///
/// Order By JObject Array
///
///
///
///
public static JObject[] ToJObjectArray(this IOrderByExpression[] orderByExpressions) where TEntity : class
{
if (orderByExpressions == null || orderByExpressions.Length == 0) return null;
List orderByList = new List();
foreach (var item in orderByExpressions)
{
orderByList.Add(item.ToJObject());
}
return orderByList.ToArray();
}
///
/// Update JObject
///
///
/// updateExpression
///
public static JObject ToJObject(this Expression> updateExpression) where TEntity : class
{
string predicateJson = JsonSerializerUtils.SerializeText(updateExpression);
if (string.IsNullOrEmpty(predicateJson))
{
return null;
}
return JObject.Parse(predicateJson);
}
}
///
///
///
public static partial class OrleansJsonExtension
{
///
///
///
///
///
///
public static Expression> ToPredicate(this JObject jsonObject) where TEntity : class
{
if (jsonObject == null) return null;
var result = JsonSerializerUtils.DeserializeJObject(jsonObject);
if (result == null)
{
return null;
}
else
{
return result as Expression>;
}
}
///
///
///
///
///
///
public static IOrderByExpression ToOrderBy(this JObject jsonObject) where TEntity : class
{
if (jsonObject == null) return null;
var expressionTxt = jsonObject["expression"].ToString();
if (string.IsNullOrEmpty(expressionTxt)) return null;
var descending = (bool)jsonObject["descending"];
var strPropertyType = jsonObject["propertyType"].ToString();
var expression = JsonSerializerUtils.DeserializeText(expressionTxt);
if (expression == null)
{
return null;
}
else
{
Type genericType = typeof(OrderByExpression<,>);
Type propertyType = Type.GetType(strPropertyType);
Type[] typeArgs = { typeof(TEntity), propertyType };
Type implementType = genericType.MakeGenericType(typeArgs);
//var tmpOrderByExpression = expression as Expression>;
//return new OrderByExpression(tmpOrderByExpression, descending);
//var instance= Activator.CreateInstance(implementType, new object[] { expression, descending });
#region 动态的泛型类型 暂时想不到更好的办法
if (propertyType == typeof(int))
{
return GetOrderByExpression(expression, descending);
}
if (propertyType == typeof(uint))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(short))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(ushort))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(long))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(ulong))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(string))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(double))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(decimal))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(float))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(byte))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(sbyte))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(DateTime))
{
return GetOrderByExpression(expression, descending);
}
else if (propertyType == typeof(Guid))
{
return GetOrderByExpression(expression, descending);
}
else
{
return null;
}
#endregion
}
}
///
///
///
///
///
///
///
///
private static IOrderByExpression GetOrderByExpression(Expression expression, bool descending) where TEntity : class
{
var tmpOrderByExpression = expression as Expression>;
return new OrderByExpression(tmpOrderByExpression, descending);
}
///
///
///
///
///
public static IOrderByExpression[] ToOrderByArray(this JObject[] jsonObjects) where TEntity : class
{
if (jsonObjects == null || jsonObjects.Length == 0)
{
return null;
}
List> orderByList = new List>();
foreach (var item in jsonObjects)
{
orderByList.Add(item.ToOrderBy());
}
return orderByList.ToArray();
}
///
///
///
///
///
///
public static Expression> ToUpdateExpression(this JObject jsonObject) where TEntity : class
{
if (jsonObject == null) return null;
var result = JsonSerializerUtils.DeserializeJObject(jsonObject);
if (result == null)
{
return null;
}
else
{
return result as Expression>;
}
}
}
///
///
///
public partial class JsonSerializerUtils
{
private static ExpressionSerializer serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());
///
///
///
///
///
///
public static string SerializeText(Expression> predicate) where TEntity : class
{
return serializer.SerializeText(predicate);
}
///
///
///
///
///
///
public static string SerializeText(Expression> expression) where TEntity : class
{
return serializer.SerializeText(expression);
}
///
///
///
///
///
public static Expression DeserializeJObject(JObject jsonObject)
{
if (jsonObject==null)
{
return null;
}
string strJson = jsonObject.ToString();
if (string.IsNullOrEmpty(strJson)) return null;
return serializer.DeserializeText(strJson);
}
///
///
///
///
///
public static Expression DeserializeText(string strJson)
{
if (string.IsNullOrEmpty(strJson)) return null;
return serializer.DeserializeText(strJson);
}
}
}
Grain对应的测试代码如下
///
/// Used to get all entities based on given .
///
/// A condition to filter entities
/// order by
/// List of all entities
public virtual async Task> GetListAsync(JObject jsonPredicate, params JObject[] jsonOrderByExpressions)
{
Expression> predicate = jsonPredicate.ToPredicate();
IOrderByExpression[] orderByExpressions = jsonOrderByExpressions.ToOrderByArray();
return await service.GetListAsync(predicate, orderByExpressions);
}
Orleans.Server 配置如下
Orleans.Client配置如下:
测试代码如下
Expression> predicate = x => x.Id >= 100 && x.Id < 105;
Action> orderAction = (o =>
{
o.Desc(x => x.AreaID).Asc(x => x.CreateUser);
});
var orderByExpressions = new IOrderByExpression[] {
new OrderByExpression(u => u.AreaID), // a string, asc
new OrderByExpression(u => u.Id, true)
};
var result = await grain.GetListAsync(predicate.ToJObject(),
orderByExpressions.ToJObjectArray());