简体   繁体   English

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

[英]What's the best way to define & access selected properties in C#?

From my recent question , I try to centralize the domain model by including some silly logic in domain interface. 我最近的问题 ,我尝试通过在域界面中包含一些愚蠢的逻辑来集中域模型。 However, I found some problem that need to include or exclude some properties from validating. 但是,我发现了一些需要在验证中包含或排除某些属性的问题。

Basically, I can use expression tree like the following code. 基本上,我可以像下面的代码一样使用表达式树。 Nevertheless, I do not like it because I need to define local variable ("u") each time when I create lambda expression. 不过,我不喜欢它,因为每次创建lambda表达式时我都需要定义局部变量(“u”)。 Do you have any source code that is shorter than me? 你有比我短的源代码吗? Moreover, I need some method to quickly access selected properties. 此外,我需要一些方法来快速访问选定的属性。

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

Thanks, 谢谢,

Lambdas are great for many scenarios - but if you don't want them, perhaps simply don't use them? Lambdas适用于许多场景 - 但如果您不想要它们,可能根本就不使用它们? I hate to say it, but simple strings are tried and tested, especially for scenarios like data binding. 我不想这么说,但是对简单的字符串进行了尝试和测试,特别是对于数据绑定等场景。 If you want fast access, you could look at HyperDescriptor, or there are ways of compiling a delegate to the property accessors, or you can build an Expression from the string and compile it (including a cast to object if you want a known signature, rather than calling the (much slower) DynamicInvoke ). 如果你想要快速访问,你可以查看HyperDescriptor,或者有方法编译属性访问器的委托,或者你可以从字符串构建一个Expression并编译它(如果你想要一个已知的签名,包括一个转换为object ,而不是调用(慢得多) DynamicInvoke )。

Of course, in most cases even crude reflection is fast enough, and isn't the bottleneck. 当然,在大多数情况下,即使粗反射也足够快,而且不是瓶颈。

I suggest starting with the simplest code, and check it is actually too slow before worrying about it being fast. 我建议从最简单的代码开始,检查它实际上是太慢了,然后再担心它的速度很快。 If it isn't too slow, don't change it. 如果不是太慢,请不要更改它。 Any of the above options would work otherwise. 除非上述任何选项都有效。


Another thought; 另一个想法; if you are using Expression , you could do something like: 如果您正在使用Expression ,您可以执行以下操作:

public void IncludeProperties<T>(
    Expression<Func<T,object>> selectedProperties)
{
    // some logic to store parameter   
}

IncludeProperties<IUser>( u => new { u.ID, u.LogOnName, u.HashedPassword });

and then take the expression apart? 然后把表达分开? A bit tidier, at least... here's some sample code showing the deconstruction: 有点整洁,至少......这里有一些展示解构的示例代码:

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

Once you know the MemberInfo s ( me.Member in the above), building your own lambdas for individual access should be trivial. 一旦你知道了MemberInfo (上面的me.Member ),为个人访问建立你自己的lambdas应该是微不足道的。 For example (including a cast to object to get a single signature): 例如(包括转换为object以获取单个签名):

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

Here's the shortest expression I can come up with: 这是我能提出的最短的表达方式:

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM