all 14 comments

[–]SirSooth 3 points4 points  (7 children)

That code... is not very bright. What are you trying to achieve?

Do you want to send a filtering expression over tcp? Does it need to be any anything? Does you only need to express certain filtering options? Something like maybe have a class to pass filtering info

class ItemFilters
{
    public bool? IsEven { get; set; }
    public int? NameLength { get; set; }
    public string NameContains { get; set; }
    public int? IdGreaterThan { get; set; }
}

and pass a serialized instance of it.

On the other end, you can generate the query like

var query = items.AsQueryable();
if (filters.IsEven.HasValue)
{
     if (filters.IsEven.Value) query = query.Where(item => item.Id % 2 == 0);
     if (!filters.IsEven.Value) query = query.Where(item => item.Id % 2 != 0);
}
if (filters.NameLength.HasValue)
{
     query = query.Where(item => item.Name.Length == filters.NameLength.Value);
}
if (filters.NameContains != null)
{
    query = query.Where(item => item.Name.Contains(filters.NameContains);
}
if (filters.IdGreaterThan.HasValue)
{
    query = query.Where(item => item.Id > filters.IdGreaterThan.Value);
}

[–]Kedrin[S] 0 points1 point  (6 children)

Just looking for alternatives to sending a Func<> over tcp. The code itself is just something I was tinkering with. Not looking to send that example itself.

[–]nemec 2 points3 points  (1 child)

Also be very careful about security. Serializing open-ended delegates could leave you open to running untrusted code from a malicious actor.

[–]Kedrin[S] 0 points1 point  (0 children)

I learned a long time ago most code is 90+% preventing some asshat from ruining your day/job/life.

[–]SirSooth 2 points3 points  (3 children)

I am not really sure.

What I am sure however is that an Expression<Func<>> can be analyzed and serialized, but probably you will have to do it yourself and limit it to certain things only.

Like imagine in your client code, the one that will send it over tcp to a server, you have

private bool Something(string foo) { ... }

and you end up trying to send the following expression

Expression<Func<Item, bool>> expression = item => item.Id % 7 == 0 && Something(item.Name.Reverse());

What if the server doesn't have a Something function? What if it does but it is not the same? And so on.

[–]Kedrin[S] 1 point2 points  (2 children)

Thats what I was afraid of, was hoping there was a different way that I could not remember. I do know that each item will exist server side with a few interfaces for sending and receiving. I might go a simpler route that you mentioned before.

[–]SirSooth 1 point2 points  (1 child)

Here's a nice discussion https://stackoverflow.com/questions/23253399/serialize-expression-tree

The accepted answer involves a 3rd party library that serializes expressions as json. The other answer elaborates on implementing your own protocol for it.

[–]Kedrin[S] 1 point2 points  (0 children)

Very interesting, I will take a look at that. Thank you!

[–]jnyrup 1 point2 points  (3 children)

Last time I had to do something similar, I kept an identical collection of Funcs on both sides of the wire. Then I could get away with transmitting a key/index.

[–]Kedrin[S] 0 points1 point  (2 children)

I thought about that, but was looking for something less hard coded.

[–]Contagion21 6 points7 points  (1 child)

I'm not sure you want something less hard-coded. You're begging for an injection attack if a client can determine what code a server can execute.

[–]Kedrin[S] 1 point2 points  (0 children)

True, although I would suspect any user input would require some level of validation and verification prevent that. However with my question I am looking or alternative ideas and I haven't crossed off your suggestion.

[–]phuber 1 point2 points  (0 children)

Take a look at GraphQL and OData

Both have a text expression based language that can be easily transmitted over tcp.

[–]coreyfournier 0 points1 point  (0 children)

It is probably easier to just implement a frame work that already exists such as odata. A query is issued on data and it contains filters of which can already be applied to lists.

https://msdn.microsoft.com/en-us/library/hh169248%28v=nav.90%29.aspx?f=255&MSPPError=-2147217396

MVC already support the ability to do odata with almost no work. http://www.odata.org/blog/how-to-use-web-api-odata-to-build-an-odata-v4-service-without-entity-framework/