Reputation: 27585
I'm new to lambda. So excuse me if my question is simple.
I have a method that uses reflection to set a property on some types:
public void WriteId(object obj, int id) {
var type = obj.GetType();
var prop = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanRead && p.CanWrite)
.Where(p => p.Name == "Id")
.Where(p.PropertyType == typeof(int))
.FirstOrDefault();
if(prop != null)
prop.SetValue(obj, id, null);
}
Can you show me please how can I create a lambda that do same job? Actually I want to create a lambda for each type, compile it, and cache it. Thanks in advance.
Upvotes: 2
Views: 558
Reputation: 1062945
I would install FastMember from NuGet, and then use:
var wrapped = ObjectAccessor.Create(obj);
obj["Id"] = id;
which does pretty much what you say, except it happens to use ILGenerator
via TypeBuilder
(rather than Expression
) - but all the caching etc is there.
A second cheaky approach is to get dynamic
to do it all for you:
((dynamic)obj).Id = id;
But if you want to use Expression
for other reasons:
using System;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
var obj = new Foo { Id = 2 };
WriteId(obj, 6);
Console.WriteLine(obj.Id); // 6
}
private static class SneakyCache<T>
{
public static readonly Action<T, int> SetId;
static SneakyCache()
{
var obj = Expression.Parameter(typeof(T), "obj");
var id = Expression.Parameter(typeof(int), "id");
SetId = Expression.Lambda<Action<T, int>>(
Expression.Assign(Expression.Property(obj, "Id"), id),
obj, id).Compile();
}
}
public static void WriteId<T>(T obj, int id) where T : class
{
SneakyCache<T>.SetId(obj, id);
}
}
class Foo
{
public int Id { get; set; }
}
Upvotes: 4