how to turn a string into a linq expression?
Solution 1
Here's an expression tree attempt. I still don't know if this would work with Entity framework, but I figure it is worth a try.
Func<T, int> MakeGetter<T>(string propertyName)
{
ParameterExpression input = Expression.Parameter(typeof(T));
var expr = Expression.Property(input, typeof(T).GetProperty(propertyName));
return Expression.Lambda<Func<T, int>>(expr, input).Compile();
}
Call it like this:
Build<T>(repo.getList(), MakeGetter<T>(classTypeId))
If you can use an Expression<Func<T,int>>
in place of a just a Func
, then just remove the call to Compile
(and change the signature of MakeGetter
).
Edit:
In the comments, TravisJ asked how he could use it like this: w => "text" + w.classTypeId
There's several ways to do this, but for readability I would recommend introducing a local variable first, like this:
var getId = MakeGetter<T>(classTypeId);
return w => "text" + getId(w);
The main point is that the getter is just a function, and you can use it exactly like you normally would. Read Func<T,int>
like this: int DoSomething(T instance)
Solution 2
Here is an extension method for you with my testing code (linqPad):
class test
{
public string sam { get; set; }
public string notsam {get; set; }
}
void Main()
{
var z = new test { sam = "sam", notsam = "alex" };
z.Dump();
z.GetPropertyByString("notsam").Dump();
z.SetPropertyByString("sam","john");
z.Dump();
}
static class Nice
{
public static void SetPropertyByString(this object x, string p,object value)
{
x.GetType().GetProperty(p).SetValue(x,value,null);
}
public static object GetPropertyByString(this object x,string p)
{
return x.GetType().GetProperty(p).GetValue(x,null);
}
}
results:
Solution 3
I haven't tried this, and not sure if it would work, but could you use something like:
b => b.GetType().GetProperty(classTypeId).GetValue(b, null);
Related videos on Youtube
Travis J
I really appreciate the Stack Exchange community. This isn't a terrible search . VP of a medium company, B.S. in Computer Science, mostly working with the ASP.NET MVC technology stack. I am the only person at the company who deals with software development making me fill the rolls of a software designer, programmer, dba, server admin, and graphics artist. As you can see from my gravatar, this causes me to wear many hats (hint: they are all from an old winterbash). My main goals when designing and coding are: how can I make the user experience easiest, and how can I reduce redundancy. "Acknowledge your faults so you can overcome them."
Updated on September 15, 2022Comments
-
Travis J over 1 year
Similar: Convert a string to Linq.Expressions or use a string as Selector?
A similar one of that one: Passing a Linq expression as a string?
Another question with the same answer: How to create dynamic lambda based Linq expression from a string in C#?
Reason for asking something which has so many similar questions:
The accepted answer in those similar questions is unacceptable in that they all reference a library from 4 years ago (granted that it was written by code master Scott Gu) written for an old framework (.net 3.5) , and does not provide anything but a link as an answer.
There is a way to do this in code without including a whole library.
Here is some sample code for this situation:
public static void getDynamic<T>(int startingId) where T : class { string classType = typeof(T).ToString(); string classTypeId = classType + "Id"; using (var repo = new Repository<T>()) { Build<T>( repo.getList(), b => b.classTypeId //doesn't compile, this is the heart of the issue //How can a string be used in this fashion to access a property in b? ) } } public void Build<T>( List<T> items, Func<T, int> value) where T : class { var Values = new List<Item>(); Values = items.Select(f => new Item() { Id = value(f) }).ToList(); } public class Item { public int Id { get; set; } }
Note that this is not looking to turn an entire string into an expression such as
query = "x => x.id == somevalue";
But instead is trying to only use the string as the access
query = x => x.STRING;
-
Hogan almost 12 yearsIf you want to put a bounty on this question you should do so, saying such-and-such answer will be bountied is silly.
-
Travis J almost 12 years@Hogan - Sorry, I cannot post a bounty for another 2 days. If I could I would. Perhaps that is an issue you can raise on meta.
-
-
Travis J almost 12 yearsThis looks interesting and at least compiles. Still have more testing to do.
-
Hogan almost 12 yearsI was able to get this to work in linqPad -- here is the code gist.github.com/3108507
-
Travis J almost 12 years@Paul - Thank you for some working code and example. I was also able to get this to work. I did not change the signature because it would have interfered with more linq down the line. I did have one question, what would I have to do to use
MakeGetter
in this way:w => "text" + MakeGetter<T>(classTypeId)
? Similar tow => "text" + w.classTypeId
. -
Travis J almost 12 yearsThis works in your example, however, I see no integration with linq here. See Paul's answer for a linq integration.
-
Hogan almost 12 yearsI guess, his works on a type mine works on an object... 6 of one. I think mine would be more performent since there is no templating needed.
-
Travis J almost 12 years@PaulPhillips - Thank you for the edit, and clarification. Although I have read a lot of documentation at MSDN and around the web I am still getting used to delegates, Funcs, and Expression trees. I appreciate it.