멤버 식의 값에 액세스
제품이 있다면.
var p = new Product { Price = 30 };
다음 linq 쿼리가 있습니다.
var q = repo.Products().Where(x=>x.Price == p.Price).ToList()
IQueryable 공급자에서 상수 표현식을 포함하는 p.Price에 대한 MemberExpression을 다시 얻지 만 "30"값을 다시 가져올 수 없습니다.
업데이트 시도했지만 작동하지 않는 것 같습니다.
var memberExpression = (MemberExpression)GetRootConstantExpression(m);
var fi = (PropertyInfo)memberExpression.Member;
var val = fi.GetValue(((ConstantExpression)memberExpression.Expression).Value, null);
건배.
본문이 멤버 액세스 인 람다 식을 컴파일하고 호출 할 수 있습니다.
private object GetValue(MemberExpression member)
{
var objectMember = Expression.Convert(member, typeof(object));
var getterLambda = Expression.Lambda<Func<object>>(objectMember);
var getter = getterLambda.Compile();
return getter();
}
로컬 평가는 표현식 트리를 구문 분석 할 때 일반적인 기술입니다. LINQ to SQL은 꽤 많은 곳에서이 작업을 수행합니다.
MemberExpression right = (MemberExpression)((BinaryExpression)p.Body).Right;
Expression.Lambda(right).Compile().DynamicInvoke();
상수 표현식은 컴파일러에 의해 생성 된 캡처 클래스를 가리킬 것입니다. 나는 결정 포인트 등을 포함하지 않았지만 여기에서 30을 얻는 방법이 있습니다.
var p = new Product { Price = 30 };
Expression<Func<Product, bool>> predicate = x => x.Price == p.Price;
BinaryExpression eq = (BinaryExpression)predicate.Body;
MemberExpression productToPrice = (MemberExpression)eq.Right;
MemberExpression captureToProduct = (MemberExpression)productToPrice.Expression;
ConstantExpression captureConst = (ConstantExpression)captureToProduct.Expression;
object product = ((FieldInfo)captureToProduct.Member).GetValue(captureConst.Value);
object price = ((PropertyInfo)productToPrice.Member).GetValue(product, null);
price
지금 30
입니다. 나는 그것이 Price
속성 이라고 가정하고 있지만 실제로 GetValue
는 속성 / 필드를 처리 하는 메서드를 작성 합니다.
q
유형 List<Product>
입니다. 목록에는 가격 속성이 없으며 개별 제품 만 있습니다.
첫 번째 또는 마지막 제품에는 가격이 있습니다.
q.First().Price
q.Last().Price
컬렉션에 하나만 있다는 것을 알고 있다면 Single을 사용하여 평면화 할 수도 있습니다.
q.Single().Price
다음을 사용할 수 있습니다.
var price = p.Price;
var q = repo.Products().Where(x=>x.Price == price).ToList()
사용 Expression.Lambda(myParameterlessExpression).Compile().Invoke()
에는 몇 가지 단점이 있습니다.
.Compile()
입니다 느린 . 작은 표현 조각의 경우에도 완료하는 데 몇 밀리 초가 걸릴 수 있습니다.Invoke
울어은, 이후하지만 슈퍼 빠르고 간단한 산술 식 또는 멤버의 액세스 만 몇 나노초합니다..Compile()
MSIL 코드를 생성 (방출)합니다. 완벽하게 들릴 수 있지만 (뛰어난 실행 속도를 설명합니다) 문제는 다음과 같습니다.이 코드는 메모리를 차지 하므로 GC가 위임 참조를 수집 한 경우에도 애플리케이션이 완료되기 전에 해제 할 수 없습니다 !
One can either avoid Compile()
altogether to avoid these issues or cache the compiled delegates for re-using them. This little library of mine offers both interpretation of Expressions
as well as cached compilation, where all constants and closures of the expression get replaced by additional parameters automatically, which are then re-inserted in a closure, which is returned to the user. Both processes are well-tested, used in production, both have their pros and cons against each other but are well over 100x faster than Compile()
- and avoid the memory leak!
And what exactly are you trying to accomplish?
Because to access the value of Price
, you'd have to do something like:
var valueOfPrice = q[0].Price;
If you had a class:
public class Item
{
public int Id { get; set; }
}
and an instance of the object:
var myItem = new Item { Id = 7 };
You can get the value of Id using an Expression using the following code:
Expression<Func<Item, int>> exp = x => x.Id;
var me = exp.Body as MemberExpression;
var propInfo = me.Member as PropertyInfo;
var value = propInfo.GetValue(myItem, null);
value will contain "7"
참고URL : https://stackoverflow.com/questions/2616638/access-the-value-of-a-member-expression
'Program Tip' 카테고리의 다른 글
Bash / Debian에서 파일 생성 날짜 / 시간을 얻는 방법은 무엇입니까? (0) | 2020.11.26 |
---|---|
벡터 드로어 블을 미리 볼 수있는 방법이 있습니까? (0) | 2020.11.26 |
“LINQ 식 노드 유형 'Invoke'는 LINQ to Entities에서 지원되지 않습니다.”-당황했습니다! (0) | 2020.11.26 |
codeigniter에서 base_url () 함수가 작동하지 않습니다. (0) | 2020.11.26 |
CSV 파일에 대해 쉼표와 큰 따옴표를 동시에 이스케이프하는 방법은 무엇입니까? (0) | 2020.11.26 |