Orleans 支持Linq 表达式参数

由于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());

你可能感兴趣的:(json,runtime)