Reputation: 14417
Quick Question:
I want to display certain properties of certain entities:
public void DisplayEntity<TEntity>(TEntity entity, params Expression<Func<TEntity, TProperty>> properties)
{
// access the properties values
Console.Write(propertyValue);
}
So I can simply do this:
DisplayEntity(Contact contact, c => c.Name);
DisplayEntity(Contact contact, c => c.Name, c => c.Tel);
I'm not sure how to write the DisplayEntity
function so that you can do this.
ANSWER
Based on Florian's answer, I slightly condensed it, in keeping with the lambda expression stuff:
static void WriteEntity<T>(T entity, params Expression<Func<T, object>>[] properties)
{
properties.ToList().ForEach(x =>
{
var f = x.Compile();
MemberExpression me;
switch (x.Body.NodeType)
{
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
var ue = x.Body as UnaryExpression;
me = ((ue != null) ? ue.Operand : null) as MemberExpression;
break;
default:
me = x.Body as MemberExpression;
break;
}
var memberInfo = me.Member;
Console.WriteLine("{0}: {1}", memberInfo.Name, f(entity));
});
}
Upvotes: 3
Views: 796
Reputation: 1098
Like this:
void ShowPropertyName<T1, T2>(T1 p, params Expression<Func<T1, T2>>[] properties)
{
foreach (var e in properties)
{
var f = e.Compile();
var memberExpression = e.Body as MemberExpression;
var memberInfo = memberExpression.Member;
Console.WriteLine("{0}: {1}", memberInfo.Name, f(p));
}
}
This would give you the name of the property and its value.
UPDATE:
Example
class Test
{
public int P1 { get; set; }
public int P2 { get; set; }
}
var test = new Test {P1 = 5, P2 = 3};
ShowPropertyName(test, t => t.P1);
ShowPropertyName(test, t => t.P2, t => t.P1);
Result
P1: 5
P2: 3
P1: 5
UPDATE: Disclaimer: This only works for properties directly on p, every thing else should be catched.
UPDATE:
Example 2 - Allowing more then one Property type in one call:
void ShowPropertyName<T1>(T1 p, params Expression<Func<T1, object>>[] properties)
{
foreach (var e in properties)
{
var f = e.Compile();
MemberExpression memberExpression;
if (e.Body is UnaryExpression)
{
var unaryExpression = e.Body as UnaryExpression;
memberExpression = unaryExpression.Operand as MemberExpression;
}
else if(e.Body is MemberExpression)
{
memberExpression = e.Body as MemberExpression;
}
else
{
Console.WriteLine("Unsupported Body expression of type {0}", e.Body.GetType());
return;
}
var memberInfo = memberExpression.Member;
Console.WriteLine("{0}: {1}", memberInfo.Name, f(p));
}
}
Test class:
class Test
{
public int P1 { get; set; }
public int P2 { get; set; }
public string P3 { get; set; }
}
Execution:
var test = new Test {P1 = 5, P2 = 3, P3 = "hello"};
ShowPropertyName(test, t => t.P1);
ShowPropertyName(test, t => t.P2, t => t.P1, t=> t.P3);
Result:
P1: 5
P2: 3
P1: 5
P3: hello
Upvotes: 4
Reputation: 180897
This would seem to do the job in a very simple way;
public static void DisplayEntity<T>(T entity, params Func<T, Object>[] parm)
{
foreach (var func in parm)
Console.WriteLine(func(entity));
}
Upvotes: 1
Reputation: 35891
Try this:
public void DisplayEntity<TEntity, TProperty>(TEntity entity, params Expression<Func<TEntity, TProperty>>[] properties)
{
foreach (var propertyValue in properties)
{
var m = propertyValue.Compile();
Console.Write(m(entity));
}
}
//...
DisplayEntity<Contact, string>(contact, c => c.Name);
While this gets your code to compile and work somehow, it's rather useless, as the same effect can be achieved by:
public void Display(object property)
{
Console.Write(property);
}
//...
Display(contact.Name);
If you want to stick to lambdas (for educational purposes) maybe this will be better:
public void DisplayEntity<TEntity>(TEntity entity, params Expression<Func<TEntity, object>>[] properties)
{
foreach (var propertyValue in properties)
{
var m = propertyValue.Compile();
Console.Write(m(entity));
}
}
//...
DisplayEntity<Contact>(contact, c => c.Name, c => c.IsEnabled);
Upvotes: 1