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
{

/// <summary>
/// An implementation of IExternalSerializer for usage with linq types.
/// </summary>
public  class JsonSerializer : IExternalSerializer
{
    //增加自定义的处理类
    private static readonly Type JsonType = typeof(JObject);
    protected Logger logger;
    public JsonSerializer()
    {
        
    }
    /// <summary>
    /// Initializes the external serializer
    /// </summary>
    /// <param name="logger">The logger to use to capture any serialization events</param>
    public void Initialize(Logger logger)
    {
        this.logger = logger;
    }
    /// <summary>
    /// Informs the serialization manager whether this serializer supports the type for serialization.
    /// </summary>
    /// <param name="itemType">The type of the item to be serialized</param>
    /// <returns>A value indicating whether the item can be serialized.</returns>
    public bool IsSupportedType(Type itemType)
    {
        if (JsonType.IsAssignableFrom(itemType))
        {
            return true;
        }
        return false;
    }
    /// <summary>
    /// Tries to create a copy of source.
    /// </summary>
    /// <param name="source">The item to create a copy of</param>
    /// <param name="context">The context in which the object is being copied.</param>
    /// <returns>The copy</returns>
    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;
    }
    /// <summary>
    /// Tries to serialize an item.
    /// </summary>
    /// <param name="item">The instance of the object being serialized</param>
    /// <param name="context">The context in which the object is being serialized.</param>
    /// <param name="expectedType">The type that the deserializer will expect</param>
    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);
    }
    /// <summary>
    /// Tries to deserialize an item.
    /// </summary>
    /// <param name="context">The context in which the object is being deserialized.</param>
    /// <param name="expectedType">The type that should be deserialized</param>
    /// <returns>The deserialized object</returns>
    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
{

/// <summary>
/// 
/// </summary>
public static partial class ExpressionExtension
{
    /// <summary>
    /// Predicate JObject
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="predicate"></param>
    /// <returns></returns>
    public static JObject ToJObject<TEntity>(this Expression<Func<TEntity, bool>> predicate) where TEntity : class
    {
        string predicateJson = JsonSerializerUtils.SerializeText(predicate);
        if (string.IsNullOrEmpty(predicateJson))
        {
            return null;
        }
        return JObject.Parse(predicateJson);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TProperty"></typeparam>
    /// <param name="expression"></param>
    /// <returns></returns>
    public static JObject ToJObject<TEntity,TProperty>(this Expression<Func<TEntity,TProperty>> expression) where TEntity : class
    {
        string predicateJson = JsonSerializerUtils.SerializeText(expression);
        if (string.IsNullOrEmpty(predicateJson))
        {
            return null;
        }
        return JObject.Parse(predicateJson);
    }
    /// <summary>
    /// Order By JObject Array
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="orderByExpressions"></param>
    /// <returns></returns>
    public static JObject[] ToJObjectArray<TEntity>(this IOrderByExpression<TEntity>[] orderByExpressions) where TEntity : class
    {
        if (orderByExpressions == null || orderByExpressions.Length == 0) return null;
        List<JObject> orderByList = new List<JObject>();
        foreach (var item in orderByExpressions)
        {
            orderByList.Add(item.ToJObject());
        }
        return orderByList.ToArray();
    }
    /// <summary>
    /// Update JObject
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="updateExpression">updateExpression</param>
    /// <returns></returns>
    public static JObject ToJObject<TEntity>(this Expression<Func<TEntity, TEntity>> updateExpression) where TEntity : class
    {
        string predicateJson = JsonSerializerUtils.SerializeText(updateExpression);
        if (string.IsNullOrEmpty(predicateJson))
        {
            return null;
        }
        return JObject.Parse(predicateJson);
    }
}
/// <summary>
/// 
/// </summary>
public static partial class OrleansJsonExtension
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="jsonObject"></param>
    /// <returns></returns>
    public static Expression<Func<TEntity, bool>> ToPredicate<TEntity>(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<Func<TEntity, bool>>;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="jsonObject"></param>
    /// <returns></returns>
    public static IOrderByExpression<TEntity> ToOrderBy<TEntity>(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<Func<TEntity,int>>;
            //return new OrderByExpression<TEntity, int>(tmpOrderByExpression, descending);
            //var instance= Activator.CreateInstance(implementType, new object[] { expression, descending });
            #region  动态的泛型类型 暂时想不到更好的办法
            if (propertyType == typeof(int))
            {
                return GetOrderByExpression<TEntity, int>(expression, descending);
            }
            if (propertyType == typeof(uint))
            {
                return GetOrderByExpression<TEntity, uint>(expression, descending);
            }
            else if (propertyType == typeof(short))
            {
                return GetOrderByExpression<TEntity, short>(expression, descending);
            }
            else if (propertyType == typeof(ushort))
            {
                return GetOrderByExpression<TEntity, ushort>(expression, descending);
            }
            else if (propertyType == typeof(long))
            {
                return GetOrderByExpression<TEntity, long>(expression, descending);
            }
            else if (propertyType == typeof(ulong))
            {
                return GetOrderByExpression<TEntity, ulong>(expression, descending);
            }
            else if (propertyType == typeof(string))
            {
                return GetOrderByExpression<TEntity, string>(expression, descending);
            }
            else if (propertyType == typeof(double))
            {
                return GetOrderByExpression<TEntity, double>(expression, descending);
            }
            else if (propertyType == typeof(decimal))
            {
                return GetOrderByExpression<TEntity, decimal>(expression, descending);
            }
            else if (propertyType == typeof(float))
            {
                return GetOrderByExpression<TEntity, float>(expression, descending);
            }
            else if (propertyType == typeof(byte))
            {
                return GetOrderByExpression<TEntity, byte>(expression, descending);
            }
            else if (propertyType == typeof(sbyte))
            {
                return GetOrderByExpression<TEntity, sbyte>(expression, descending);
            }
            else if (propertyType == typeof(DateTime))
            {
                return GetOrderByExpression<TEntity, DateTime>(expression, descending);
            }
            else if (propertyType == typeof(Guid))
            {
                return GetOrderByExpression<TEntity, Guid>(expression, descending);
            }
            else
            {
                return null;
            }
            #endregion
        }
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TProperty"></typeparam>
    /// <param name="expression"></param>
    /// <param name="descending"></param>
    /// <returns></returns>
    private static IOrderByExpression<TEntity> GetOrderByExpression<TEntity, TProperty>(Expression expression, bool descending) where TEntity : class
    {
        var tmpOrderByExpression = expression as Expression<Func<TEntity, TProperty>>;
        return new OrderByExpression<TEntity, TProperty>(tmpOrderByExpression, descending);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    public static IOrderByExpression<TEntity>[] ToOrderByArray<TEntity>(this JObject[] jsonObjects) where TEntity : class
    {
        if (jsonObjects == null || jsonObjects.Length == 0)
        {
            return null;
        }
        List<IOrderByExpression<TEntity>> orderByList = new List<IOrderByExpression<TEntity>>();
        foreach (var item in jsonObjects)
        {
            orderByList.Add(item.ToOrderBy<TEntity>());
        }
        return orderByList.ToArray();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="jsonObject"></param>
    /// <returns></returns>
    public static Expression<Func<TEntity, TEntity>> ToUpdateExpression<TEntity>(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<Func<TEntity, TEntity>>;
        }
    }
}
/// <summary>
/// 
/// </summary>
public partial class JsonSerializerUtils
{
    private static ExpressionSerializer serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="predicate"></param>
    /// <returns></returns>
    public static string SerializeText<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
    {
        return serializer.SerializeText(predicate);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="predicate"></param>
    /// <returns></returns>
    public static string SerializeText<TEntity,TProperty>(Expression<Func<TEntity, TProperty>> expression) where TEntity : class
    {
        return serializer.SerializeText(expression);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="jsonObject"></param>
    /// <returns></returns>
    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);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="jsonObject"></param>
    /// <returns></returns>
    public static Expression DeserializeText(string strJson)
    {

        if (string.IsNullOrEmpty(strJson)) return null;
        return serializer.DeserializeText(strJson);
    }
}

}

Grain对应的测试代码如下

 /// <summary>
    /// Used to get all entities based on given <paramref name="predicate"/>.
    /// </summary>
    /// <param name="jsonPredicate">A condition to filter entities</param>
    /// <param name="jsonOrderByExpressions">order by </param>
    /// <return awaits>List of all entities</return awaits>
    public virtual async Task<List<TEntity>> GetListAsync(JObject jsonPredicate, params JObject[] jsonOrderByExpressions)
    {
        Expression<Func<TEntity, bool>> predicate = jsonPredicate.ToPredicate<TEntity>();
        IOrderByExpression<TEntity>[] orderByExpressions = jsonOrderByExpressions.ToOrderByArray<TEntity>();
        return await service.GetListAsync(predicate, orderByExpressions);
    }

Orleans.Server 配置如下

  <SerializationProviders>
      <Provider type="NoobOrleans.Core.JsonSerializer,NoobOrleans.Core"/>
  </SerializationProviders>
</Messaging>

Orleans.Client配置如下:

<SerializationProviders>
  <Provider type="NoobOrleans.Core.JsonSerializer,NoobOrleans.Core"/>
</SerializationProviders>

测试代码如下
Expression> predicate = x => x.Id >= 100 && x.Id < 105;

            Action<Orderable<AdmArea>> orderAction = (o =>
            {
                o.Desc(x => x.AreaID).Asc(x => x.CreateUser);
            });
            var orderByExpressions = new IOrderByExpression<AdmArea>[] {
                   new OrderByExpression<AdmArea, string>(u => u.AreaID),    // a string, asc
                new OrderByExpression<AdmArea, int>(u => u.Id, true)
            };
            var result = await grain.GetListAsync(predicate.ToJObject(),
             orderByExpressions.ToJObjectArray());
上一篇:Windows 下使用nginx对SqlServer进行负载均衡


下一篇:OSCache操作详解+标签使用