6 Eylül 2018 Perşembe

Expression.Parameter metodu

Giriş
Bir metoda geçilen parametre nesnesine erişmek için kullanılır. İki tane parametre alır
Birincisi parametrenin tipi, ikincisi ismidir. ParameterExpression nesnesi döner

Örnek
Şöyle yaparız.
class Program
{
  static void Main(string[] args)
  {
    var spanGetter = typeof(Program).GetMethod("GetItem").
    MakeGenericMethod(typeof(float));

    var myFloatSpan = Expression.Parameter(typeof(Span<float>), "s");

    var myValue = Expression.Call(
            null,
            spanGetter,
            myFloatSpan,
            Expression.Constant(42));

    var myAdd = Expression.Add(
            myValue,
            Expression.Constant(13f));

    var expr = Expression.Lambda<MyFunc>(myAdd, myFloatSpan).Compile();

    var span = new Span<float>(new float[43]);
    span[42] = 12.3456f;
    Console.WriteLine(expr(span)); // -> 25.3456
  }

  // hopefully, this shouldn't be too bad in terms of performance...
  // C# knows how to do compile this, while Linq Expressions doesn't
  public static T GetItem<T>(Span<T> span, int index) => span[index];

  // we need that because we can't use a Span<T> directly with Func<T>
  // we could make it generic also I guess
  public delegate float MyFunc(Span<float> span);
}
Örnek
Şöyle yaparız.
static class IdFetcher<T>
{
  public static int Fetch(T item) => fetch(item);
  static readonly Func<T, int> fetch;
  static IdFetcher()
  {
    var p = Expression.Parameter(typeof(T), "item");
    fetch = Expression.Lambda<Func<T, int>>(
      Expression.PropertyOrField(p, "Id"), p).Compile();
  }
}
Çağırmak için şöyle yaparız
int n = IdFetcher<T>IdFetcher<T>.Fetch(obj);
Örnek
Şöyle yaparız.
ParameterExpression param = Expression.Parameter(typeof(T), "t");
Örnek
Şöyle yaparız.
var param = Expression.Parameter(typeof(int), "n");
Örnek
Boat nesnesi ve buna ait Accounts listesi olsun. Elimizde bir lambda olsun
repo = repo.Where(x => x.Accounts.FirstOrDefault().Id == AccountId);
Şöyle yaparız. x nesnesi ile bir Expression oluştururuz. Bu nesnenin "Accounts" alanına erişiriz.
var parameterExp = Expression.Parameter(typeof(Boat), "x");
Expression propertyExp = Expression.Property(parameterExp, "Accounts");

Type elementType = propertyExp.Type.GetGenericArguments()[0];

MethodInfo method1 = typeof(Enumerable).GetMethods(
BindingFlags.Public | BindingFlags.Static).First(m => m.Name == "FirstOrDefault");

// This gives me a Queryable of Account FirstOrDefault
var specificMethod = method1.MakeGenericMethod(elementType);


var firstOrDefaultAccountExpression = Expression.Call(specificMethod, propertyExp);

var idExpr = Expression.PropertyOrField(firstOrDefaultAccountExpression, "Id");

MethodInfo method = typeof(long).GetMethod("Equals", new[] { typeof(long) });
var someValue = Expression.Constant(AccountId, typeof(long));
var containsMethodExp = Expression.Call(idExpr, method, someValue);

Expression<Func<Boat, bool>> predicate = Expression.Lambda<Func<Boat, bool>>
             (containsMethodExp, parameterExp);

repo = repo.Where(predicate);

Hiç yorum yok:

Yorum Gönder