표현식 트리를 통해 개체의 속성 값을 설정하는 데 필요한 유동적 인 API를 작성하려고합니다. 이 작업을 수행하는 대신 :C# 표현 트리 : 인터페이스에 엔터티 매개 변수 캐스팅
public static class Converters
{
public static SomeType ToSomeType(this Dictionary<string, string> values, string fieldName)
{
//...conversion logic
}
}
public class Target : ITarget
{
public SomeType Prop1 {get; set;}
public void SetValues(Dictionary<string, string> values)
{
Prop1 = values.ToSomeType("fieldName");
}
}
내가이 작업을 수행 할 수 있도록하고 싶습니다 :
내가하는 SetProperty 정적 방법에 대한 몇 가지 진전을했습니다public class Target : ITarget
{
public Target()
{
this.SetProperty(x=>x.Prop1, y => y.ToSomeType("fieldName"));
}
public void SetValues(Dictionary<string, string> values)
{
//...logic that executes compiled converter functions derived from
// SetProperty calls, and which are stored in an internal list
}
}
, 내가 문제로 실행 해요 넣어 내가 ITarget (내 예제에서 대상) 특정 클래스의 인스턴스 모두 같은 객체와 같은 참조 할 필요가 여기서
public static void SetProperty<TEntity, TProperty>(this TEntity target, Expression<Func<TEntity, object>> memberLambda,
Expression<Func<IImportFile, TProperty>> converter)
where TEntity: class, ITarget
{
var memberSelector = memberLambda.Body as MemberExpression;
if(memberSelector == null)
throw new ArgumentException(
$"{nameof(SetProperty)} -- invalid property specification on Type {typeof(TEntity).FullName}");
var propInfo = memberSelector.Member as PropertyInfo;
if(propInfo == null)
throw new ArgumentException(
$"{nameof(SetProperty)} -- invalid property specification on Type {typeof(TEntity).FullName}");
MethodCallExpression convMethod = converter.Body as MethodCallExpression;
if(convMethod == null)
throw new ArgumentException(
$"{nameof(SetProperty)} -- converter does not contain a MethodCallExpression on Type {typeof(IImportFile).FullName}");
ParameterExpression targetExp = Expression.Parameter(typeof(TEntity), "target");
MemberExpression propExp = Expression.Property(targetExp, propInfo);
BinaryExpression assignExp = Expression.Assign(propExp, convMethod);
// this next line throws the exception
var junk = Expression.Lambda<Action<ITarget, IImportFile>>(assignExp, targetExp,
(ParameterExpression) convMethod.Arguments[ 0 ]).Compile();
}
문제는하는 SetProperty 구현의 맨 마지막 줄에 발생합니다. 컴파일러는 두 번째 매개 변수 인 convMethod의 인수에서 파생 된 매개 변수를 허용하지 않습니다. 관련하여 TEntity! = ITarget입니다.
물론 내 예제에서 TEntity - Target은 ITarget을 구현하기 위해 정의 된 것을 제외하고는 :).
필자는 Expression 컴파일 코드가 실제로 엄격한 유형 검사를 수행하고 있다고 가정하고 매개 변수가 필요한 부분으로 캐스팅 될 수 있는지 여부를 확인하지 않습니다.
그러나 ParameterExpression을 다른 Type으로 캐스팅하는 방법을 알아낼 수는 있지만 여전히 동일한 매개 변수를 참조해야합니다. Expression.Convert()를 시도했지만 Expression.Lambda 호출이 ParameterExpression으로 사용되지 않는 UnaryExpression을 반환하기 때문에 작동하지 않습니다. 1
후속 번호는 내가 ITarget로, IImportTarget에 대한 참조를 수정했습니다. 혼란에 대해 죄송합니다.
꽤 큰 항목이기 때문에 전체 시스템을 설명하지 못했습니다. 특정 질문 - 두 개의 ParameterExpressions가 동일한 객체를 참조하는 방법은 무엇입니까? 공용 인터페이스) - 많은 곳에서 자랄 수있는 무언가입니다. HRESULT = 유형 ParameterExpression 'ConsoleApp1.TestTarget가' 는 '타입의 대리자 파라미터에 사용될 수 = -2147024809
메시지 ImportFramework.IImportTarget
System.ArgumentException 발생 : 여기
정확한 예외 메시지 인 '
자료 = System.Core 스택 트레이스 : System.Linq.Expression에서 System.Linq.Expressions.Expression.ValidateLambdaArgs에서 (타입 delegateType 표현 & 본체 ReadOnlyCollection1 parameters) at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, String name, Boolean tailCall, IEnumerable
1 개 파라미터) 표현식 본문 부울 tailCall, IEnumerable1 parameters) at ImportFramework.ImportAgentExtensions.SetProperty[TEntity,TProperty](TEntity target, Expression
1 memberLambda, Expression`1 변환기) C : \ Programming \ ConnellCampaigns \ src \ ImportFramework \ ImportAgent에있는 표현식.CS : 라인 55의 InnerException :var junk = Expression.Lambda<Action<TEntity, IImportFile>>(assignExp, targetExp, (ParameterExpression) convMethod.Arguments[ 0 ]).Compile();
및 적어도
정확한 오류가 무엇인지 말할 수 있습니다. 또한 코드가 원하는 것을 실제로 볼 수 없습니다. 문자열 값을 어떤 종류의 객체로 변환하려고합니까? 그 당시에 '객체'가 더 좋지 않겠는가? 'ITmargetTarget'은 어디에서 정의 되었습니까? 실제로'ITarget'이 링크되어있는 것처럼 보이지는 않습니다. 그러나 당신의 예제가 불완전하기 때문에있을 수 있습니다 ('where' 절의 일부가 아닙니다). – Icepickle
Please 후속 조치 # 1 참조 –