我需要帮助。 我有两个类:实体和模型。他们的代码如下。
public class TestEntityForSerialize
{
public String FIO { get; set; }
public DateTime Birthday { get; set; }
public String Name { get; set; }
}
[DataContract]
public class TestModelForSerialize
{
[DataMember]
public String FIO { get; set; }
[DataMember]
public DateTime Birthday { get; set; }
[DataMember(Name = "Name")]
public String BigName { get; set; }
public Int32 Age { get; set; }
}
主要任务是以编程方式将任何Func<TestModelForSerialize, Boolean>
转换为Func <TestEntityForSerialize, Boolean>
。我的决定是使用表达式树。我将ExpressionVisitor用于迭代模型的表达式树的节点,并构造一个新的Expression with Entity作为参数。这些Func的通用参数在类中设置,保留了功能。
我通过重写VisitParameter方法成功转换了ParameterExpression,但我仍然坚持使用ExpressionVisitor后代的重写VisitMember方法。实际上我有代码: VisitMember覆盖:
protected override Expression VisitMember(MemberExpression node)
{
Expression e = base.VisitMember(node);
MemberExpression me = e as MemberExpression;
if (me != null)
{
String modelPropertyName = ((PropertyInfo)me.Member).Name;
ParameterExpression pe = node.Expression as ParameterExpression;
TModel m = Activator.CreateInstance<TModel>();
PropertyInfo memberPI = GetEntityProperty(m, modelPropertyName);
MemberExpression meToReturn = Expression.Property(Expression.Parameter(typeof(TEntity)), memberPI);
return meToReturn;
}
else
{
return base.VisitMember(node);
}
}
VisitParameter覆盖:
protected override Expression VisitParameter(ParameterExpression node)
{
ParameterExpression pe = base.VisitParameter(node) as ParameterExpression;
if (pe.Type == typeof(TModel))
{
ParameterExpression ex = Expression.Parameter(typeof(TEntity), pe.Name);
return ex;
}
else
{
return pe;
}
}
GetEntityProperty是TModel类的方法映射属性到TEntity类的属性。它使用DataContract和DataMember进行映射。
protected PropertyInfo GetEntityProperty(TModel model, String propertyName)
{
PropertyInfo property = model.GetType().GetProperty(propertyName);
if (property != null)
{
Attribute attr = property.GetCustomAttribute(typeof(DataMemberAttribute));
if (attr != null)
{
String entityPropertyName = (((DataMemberAttribute)attr).Name != null ? ((DataMemberAttribute)attr).Name : propertyName);
return typeof(TEntity).GetProperty(entityPropertyName);
}
else
{
throw new DataMemberAttributeNotFoundException();
}
}
else
{
throw new MissingMemberException();
}
}
TestMethod是
[TestMethod]
public void TestVisitMemberShouldReplaceModelWithEntity()
{
ParameterExpression p = Expression.Parameter(typeof(TestModelForSerialize));
Type tm = typeof(TestModelForSerialize);
PropertyInfo birthdayProp = tm.GetProperty("FIO");
Assert.IsNotNull(birthdayProp);
MemberExpression me = Expression.Property(p, birthdayProp);
VisitorForTests vft = new VisitorForTests();
MemberExpression meResult = vft.VisitMemberForTest(me) as MemberExpression;
Assert.IsInstanceOfType(meResult.Member, typeof(PropertyInfo));
}
VisitorForTests是在课堂上调用受保护方法的类,我试图处理。它的方法:
public Expression VisitMemberForTest(MemberExpression node)
{
return this.VisitMember(node);
}
当我尝试调用VisitMember方法时,它会破坏第一行(&#34; Expression e = base.VisitMember(node);&#34;),抛出带有消息的ArgumentException:Property&#34; FIO& #34;没有在课程中定义&#34; TestEntityForSerialize&#34;。只有我能注意到的事情 - VisitMember尝试启动VisitParameter方法,并在得到它的结果后 - 粉碎。
非常感谢任何帮助。
答案 0 :(得分:1)
疑难杂症! 正如俄罗斯谚语所说的那样:“拯救人类正在拯救 - 这是男人自己的事业。”问题是 - 我试图使用带有错误参数的Expression。它应该提供TEntity的属性,我将提供TModel的属性。所以只需轻松改变VisitMember方法和Qawabanga!
protected override Expression VisitMember(MemberExpression node)
{
//Expression e = base.VisitMember(node); - I've commented this line
MemberExpression me = node as MemberExpression;
if (me != null)
{
String modelPropertyName = ((PropertyInfo)me.Member).Name;
ParameterExpression pe = node.Expression as ParameterExpression;
TModel m = Activator.CreateInstance<TModel>();
PropertyInfo memberPI = GetEntityProperty(m, modelPropertyName);
MemberExpression meToReturn = Expression.Property(Expression.Parameter(typeof(TEntity)), memberPI.Name);
return base.VisitMember(meToReturn); //and changed this line
}
else
{
return base.VisitMember(node);
}
}
这很有效!