代码之家  ›  专栏  ›  技术社区  ›  Soul_Master

在C#中定义和访问选定属性的最佳方法是什么?

  •  7
  • Soul_Master  · 技术社区  · 16 年前

    从…起 my recent question ,我试图通过在域接口中包含一些愚蠢的逻辑来集中域模型。但是,我发现了一些问题,需要在验证中包含或排除某些属性。

    public void IncludeProperties<T>(params Expression<Func<IUser,object>>[] selectedProperties)
    {
        // some logic to store parameter   
    }
    
    IncludeProperties<IUser>
    (
        u => u.ID,
        u => u.LogOnName,
        u => u.HashedPassword
    );
    

    谢谢

    2 回复  |  直到 9 年前
        1
  •  9
  •   Marc Gravell    16 年前

    lambda对于很多场景都很好——但是如果你不想要它们,也许干脆不使用它们?我不想这么说,但简单的字符串是经过尝试和测试的,特别是对于数据绑定之类的场景。如果您想要快速访问,可以查看HyperDescriptor,或者有一些方法可以编译属性访问器的委托,或者可以构建 Expression object 如果您想要一个已知的签名,而不是调用(慢得多) DynamicInvoke

    我建议从最简单的代码开始,并检查它是否正确 在担心速度过快之前太慢了。如果不是太慢,就不要改变它。否则,上述任何选项都会起作用。


    另一种想法;如果您正在使用 表情

    public void IncludeProperties<T>(
        Expression<Func<T,object>> selectedProperties)
    {
        // some logic to store parameter   
    }
    
    IncludeProperties<IUser>( u => new { u.ID, u.LogOnName, u.HashedPassword });
    

    然后把这个表达式拆开?至少有点整洁。。。下面是一些显示解构的示例代码:

    public static void IncludeProperties<T>(
        Expression<Func<T, object>> selectedProperties)
    {
        NewExpression ne = selectedProperties.Body as NewExpression;
        if (ne == null) throw new InvalidOperationException(
              "Object constructor expected");
    
        foreach (Expression arg in ne.Arguments)
        {
            MemberExpression me = arg as MemberExpression;
            if (me == null || me.Expression != selectedProperties.Parameters[0])
                throw new InvalidOperationException(
                    "Object constructor argument should be a direct member");
            Console.WriteLine("Accessing: " + me.Member.Name);
        }
    }
    static void Main()
    {
        IncludeProperties<IUser>(u => new { u.ID, u.LogOnName, u.HashedPassword });
    }
    

    一旦你知道了 MemberInfo ( me.Member 在上文中),为个人访问构建自己的lambda应该很简单。例如(包括对 对象 要获得单个签名,请执行以下操作:

    var param = Expression.Parameter(typeof(T), "x");
    var memberAccess = Expression.MakeMemberAccess(param, me.Member);
    var body = Expression.Convert(memberAccess, typeof(object));
    var lambda = Expression.Lambda<Func<T, object>>(body, param);
    var func = lambda.Compile();
    
        2
  •  1
  •   Peter Lillevold Rene    16 年前

    public static void IncludeProperties(Expression<Action<IUser>> selectedProperties)
    {
        // some logic to store parameter   
    }
    
    public static void S(params object[] props)
    {
        // dummy method to get to the params syntax
    }
    
    [Test]
    public void ParamsTest()
    {
        IncludeProperties(u => S(
            u.Id,
            u.Name
            ));
    
    }