Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#表达式序列化/参数替换_C#_Linq_Expression_Func - Fatal编程技术网

C#表达式序列化/参数替换

C#表达式序列化/参数替换,c#,linq,expression,func,C#,Linq,Expression,Func,首先,简要介绍一下我要做的事情:我想获取一个C#表达式,序列化它,将它发送到另一个进程,反序列化它,并使用它来过滤列表。这里有一个警告——当表达式被创建时,它是针对泛型参数类型T来创建的,但是当它被反序列化时,它需要针对动态类型。这样做的原因是,当它最终在另一个进程中的服务器上使用时,它将针对一个动态列表进行操作,因为在该上下文中我没有类型信息 我觉得我已经很接近了,因为我已经使用了Newtonsoft.Json和Serialize.Linq库来进行概念验证,但我只能在不使用动力学的情况下让它工

首先,简要介绍一下我要做的事情:我想获取一个C#表达式,序列化它,将它发送到另一个进程,反序列化它,并使用它来过滤列表。这里有一个警告——当表达式被创建时,它是针对泛型参数类型T来创建的,但是当它被反序列化时,它需要针对动态类型。这样做的原因是,当它最终在另一个进程中的服务器上使用时,它将针对一个动态列表进行操作,因为在该上下文中我没有类型信息

我觉得我已经很接近了,因为我已经使用了Newtonsoft.Json和Serialize.Linq库来进行概念验证,但我只能在不使用动力学的情况下让它工作(例如,我在序列化端(客户端)和反序列化端(服务器)都有T类型。下面是一些代码,向您展示我所拥有的

鉴于此:

public class Person
{
    public string Name { get; set; }
    public string Email { get; set; }
}
…作为我们正在使用的类型。我有一个具有以下接口的客户端:

public interface IClient
{
    T Get<T>(Expression<Func<T, bool>> query);
}
公共接口IClient
{
T-Get(表达式查询);
}
…这样我就能做到:

var client = new Client();
var john = client.Get<Person>(p => p.Name == "John");
var client=new client();
var john=client.Get(p=>p.Name==“john”);
…到目前为止一切都很好。在client.Get()方法中,我获取传递的表达式并将其序列化,然后发送到服务器。服务器看起来如下:

 public dynamic Server(string serializedExpression)
 {
    var people = new List<dynamic>
    {
        new { Name = "John", Email = "john@stackoverflow.com" },
        new { Name = "Jane", Email = "jane@stackoverflow.com" }
    };

    var serializer = new ExpressionSerializer(new JsonSerializer());
    var deserializedExpression = (Expression<Func<dynamic, bool>>)serializer.DeserializeText(serializedExpression);

    return people.FirstOrDefault(deserializedExpression.Compile());
}
公共动态服务器(字符串序列化显示)
{
var people=新列表
{
新的{Name=“John”,电子邮件=”john@stackoverflow.com" },
新的{Name=“Jane”,电子邮件=”jane@stackoverflow.com" }
};
var serializer=newexpressionserializer(newjsonserializer());
var deserializedExpression=(表达式)序列化程序。DeserializeText(serializedExpression);
返回people.FirstOrDefault(反序列化dexpression.Compile());
}
…这里是问题发生的地方,因为我正试图将其反序列化为

Expression<Func<dynamic, bool>> 
表达式
…而不是

Expression<Func<Person, bool>>.
表达式。
因此,我的问题是:

1) 我想做的事可能吗?似乎使用ExpressionVisitor可以更改泛型参数类型,在序列化和发送之前,我尝试过从Person更改为dynamic,但没有成功

2) 有没有更好的方法来完成我想完成的事情?我知道第一个问题是为什么我不能访问服务器上表达式Func中指定的类型t,但由于服务器的性质,这是不可能的。我基本上希望在客户端上使用Linq来指定查询谓词,同时对动态列表执行这些谓词

提前感谢您提供的任何答案或想法

问候,

Craig

LINQ动力学在表达式中的应用非常广泛。(也许是德林克?)

或者,您可以向服务器传递一个关于正在使用的对象类型的提示。我意识到这可能不是你想要的,但它正在发挥作用:

(借用自)

公共静态类扩展
{
公共静态对象ToType(此对象obj,T类型)
{
//创建T类型对象的实例:
var tmp=Activator.CreateInstance(Type.GetType(Type.ToString());
//循环遍历要转换的对象的属性:
foreach(obj.GetType().GetProperties()中的PropertyInfo pi)
{
尝试
{
//获取属性的值并重试
//要将其指定给T类型对象的属性,请执行以下操作:
tmp.GetType().GetProperty(pi.Name).SetValue(tmp,
pi.GetValue(obj,null),null);
}
捕获{}
}
//返回T类型对象:
返回tmp;
}
公共静态对象ToNonAnonymousList(此列表,类型t)
{
//定义表示T类型对象列表的系统类型:
var genericType=typeof(列表)。MakeGenericType(t);
//创建定义类型的对象实例:
var l=Activator.CreateInstance(genericType);
//从列表中获取方法Add:
MethodInfo addMethod=l.GetType().GetMethod(“添加”);
//在调用列表中循环:
foreach(列表中的T项)
{
//将列表中的每个对象转换为T对象
//通过调用扩展名ToType()
//将此对象添加到新创建的列表:
Invoke(l,新对象[]{item.ToType(t)});
}
//返回T对象的列表:
返回l;
}
}
。。。在服务器上有一些不太好的分支:

public interface IClient
{
    T Get<T>(Expression<Func<T, bool>> query);
}

public class Person
{
    public string Name { get; set; }
    public string Email { get; set; }
}

public class Client
{
    public T Get<T>(Expression<Func<dynamic, bool>> query)
    {
        var serializer = new ExpressionSerializer(new JsonSerializer());
        var serializedExpression = serializer.SerializeText(query);
        return (T)Server.Retrieve(serializedExpression, typeof(T).FullName);
    }
}

public static class Server
{
    public static dynamic Retrieve(string serializedExpression, string targetType)
    {
        var people = new List<dynamic> 
            {
                new { Name = "John", Email = "john@stackoverflow.com" },
                new { Name = "Jane", Email = "jane@stackoverflow.com" }
            };

        // Try creating an object of the type hint passed to the server
        var typeInstance = Activator.CreateInstance(Type.GetType(targetType));

        if (typeInstance.GetType() == typeof(Person))
        {
            var serializer = new ExpressionSerializer(new JsonSerializer());
            var deserializedExpression = (Expression<Func<Person, bool>>)serializer.DeserializeText(serializedExpression);
            var peopleCasted = (IEnumerable<Person>)people.ToNonAnonymousList(typeof(Person));
            return peopleCasted.Where(deserializedExpression.Compile()).SingleOrDefault();
        }
        else
        {
            throw new ArgumentException("Type is unknown");
        }
    }
}
公共接口IClient
{
T-Get(表达式查询);
}
公共阶层人士
{
公共字符串名称{get;set;}
公共字符串电子邮件{get;set;}
}
公共类客户端
{
公共T获取(表达式查询)
{
var serializer=newexpressionserializer(newjsonserializer());
var serializedExpression=serializer.SerializeText(查询);
return(T)Server.Retrieve(serializedPression,typeof(T).FullName);
}
}
公共静态类服务器
{
公共静态动态检索(string SerializedPression,string targetType)
{
var people=新列表
{
新的{Name=“John”,电子邮件=”john@stackoverflow.com" },
新的{Name=“Jane”,电子邮件=”jane@stackoverflow.com" }
};
//尝试创建传递给服务器的提示类型的对象
var typeInstance=Activator.CreateInstance(Type.GetType(targetType));
if(typeInstance.GetType()==typeof(Person))
{
var serializer=newexpressionserializer(newjsonserializer());
var deserializedExpression=(表达式)序列化程序。DeserializeText(serializedExpression);
var peopleCasted=(IEnumerable)people.ToNonAnonymousList(typeof(Person));
回归人民
public interface IClient
{
    T Get<T>(Expression<Func<T, bool>> query);
}

public class Person
{
    public string Name { get; set; }
    public string Email { get; set; }
}

public class Client
{
    public T Get<T>(Expression<Func<dynamic, bool>> query)
    {
        var serializer = new ExpressionSerializer(new JsonSerializer());
        var serializedExpression = serializer.SerializeText(query);
        return (T)Server.Retrieve(serializedExpression, typeof(T).FullName);
    }
}

public static class Server
{
    public static dynamic Retrieve(string serializedExpression, string targetType)
    {
        var people = new List<dynamic> 
            {
                new { Name = "John", Email = "john@stackoverflow.com" },
                new { Name = "Jane", Email = "jane@stackoverflow.com" }
            };

        // Try creating an object of the type hint passed to the server
        var typeInstance = Activator.CreateInstance(Type.GetType(targetType));

        if (typeInstance.GetType() == typeof(Person))
        {
            var serializer = new ExpressionSerializer(new JsonSerializer());
            var deserializedExpression = (Expression<Func<Person, bool>>)serializer.DeserializeText(serializedExpression);
            var peopleCasted = (IEnumerable<Person>)people.ToNonAnonymousList(typeof(Person));
            return peopleCasted.Where(deserializedExpression.Compile()).SingleOrDefault();
        }
        else
        {
            throw new ArgumentException("Type is unknown");
        }
    }
}
[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void MyTestMethod()
    {
        var client = new Client();
        var john = client.Get<Person>(p => p.Name == "John");
        Assert.IsNotNull(john);
    }
}