未定义成员表达式属性

本文关键字:属性 表达式 成员 未定义 | 更新日期: 2023-09-27 18:32:12

我需要帮助。我有两个类:实体和模型。他们的代码如下。

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 来迭代模型的表达式树的节点,并使用实体作为参数构造一个新的表达式。这些 Func 的通用参数在类中设置,保存功能。

我已经通过覆盖VisitParameter方法成功地转换了ParameterExpression,但是我卡住了覆盖ExpressionVisitor后代的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);
        }
    }

访问参数覆盖:

    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]
    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 方法时,它会压在第一行("表达式 e = base。VisitMember(node);"),抛出带有消息的 ArgumentException:属性"FIO"未在类 "TestEntityForSerialize" 中定义。我唯一能注意到的 - 访问会员尝试启动访问参数方法,并在得到它的结果后 - 粉碎。

任何帮助都非常感谢。

未定义成员表达式属性

明白了!正如俄罗斯谚语所说:"沉没的人拯救 - 这个人的手是自己的事。问题是 - 我试图使用带有错误参数的表达式。它应该提供 TEntity 的属性,我会提供它 TModel 的属性。所以只需轻轻改变访问会员方法和卡瓦班加!

    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);
        }
    }

这行得通!