简体   繁体   English

属性作为参数? C#

[英]Property as parameter? C#

So I've got a whole bunch of options, every different page/tab can have their own local options. 所以我有很多选项,每个不同的页面/选项卡都可以有自己的本地选项。 We'll have maybe 10-15 pages tabs open tops. 我们可能会在顶部打开10-15页的标签。 I need to implement a way to show the global defaults, weather the all the tabs have consistent values. 我需要实现一种方法来显示全局默认值,使所有选项卡具有一致的值。 I'm working on the model/viewmodel portion of a WPF app. 我正在WPF应用程序的模型/视图模型部分。

I'd love to find a way that is more elegant since I'm having to cut and past roughly the same code 20+ times and just change property names. 我想找到一种更优雅的方法,因为我不得不将大约相同的代码剪切和跳过20多次以上,并且只需更改属性名称即可。 Maybe this is the problem Dynamics solve, but right now this feels both wrong and painful. 也许这是Dynamics解决的问题,但是现在这感觉既错又痛苦。

Here is an example of my current solution: 这是我当前解决方案的一个示例:

public class Foo
{
    private bool fooVar1;
    private bool fooVar2;
    //lots of these
    private decimal fooVar23;

    public Foo()
    {
    }

    public bool FooVar1
    {
        get;
        set;
    }

    //you get the picture...
}

public class FooMonitor
{
    private Foo defaultFoo;
    private List<Foo> allFoos;

    public FooMonitor(Foo DefaultFoo)
    {
        defaultFoo = DefaultFoo;
    }

    public void AddFoo(Foo newFoo)
    {
        allFoos.Add(newFoo);
    }

    public void AddFoo(Foo oldFoo)
    {
        allFoos.Remove(oldFoo);
    }

    public bool IsFooVar1Consistent
    {
        get
        {
            Foo[] tempFoos = allFoos.ToArray();
            foreach (Foo tempFoo in tempFoos)
            {
                if (tempFoo.FooVar1 != defaultFoo.FooVar1) return false;
            }
            return true;
        }
    }
}

Or am I approaching this problem entirely incorrectly. 还是我完全错误地解决了这个问题。 As I'm writing this question (After about 2000 lines of code) I'm thinking of how I read that WPF itself implements Dictionary look ups that crawl up to the parent to see if a Property is present and what the value should be. 当我写这个问题时(大约经过2000行代码),我在想我是如何阅读WPF本身实现的字典查找的,爬升到父级以查看是否存在Property以及值应该是什么。

Well, for a start you are defining both backing fields which will never be used and automatic properties. 好吧,首先,您要定义永远不会使用的后备字段和自动属性。 This is enough for a simple bool property: 这对于一个简单的bool属性就足够了:

public bool FooVar1 { get; set; }

No need for the private field. 不需要私有领域。 This greatly reduces the number of lines in your example. 这大大减少了示例中的行数。

I'm not quite sure what the question is, but if you're looking for some way to unify the IsFoorVarXConsistent code, you could do it using reflection or by passing in an expression: 我不太确定问题是什么,但是如果您正在寻找某种方法来统一IsFoorVarXConsistent代码,则可以使用反射或通过传递表达式来实现:

public bool IsConsistent(Func<Foo, bool> property)
{
  foreach (Foo tempFoo in allFoos)
  {
    if (property(tempFoo) != property(defaultFoo))
      return false;
  }
  return true;
}

Called like this: 这样称呼:

bool is1Consistent = IsConsistent(f => f.FooVar1);

As shown this will only work for boolean properties. 如图所示,这仅适用于布尔属性。 To extend it to other types, we can make it generic in the property type. 为了将其扩展为其他类型,我们可以使其在属性类型中通用。 However, in this case we cannot use != to test for inequality because not all types define a != operator. 但是,在这种情况下,我们不能使用!=来测试不等式,因为并非所有类型都定义!=运算符。 Instead we can use the .Equals method and the ! 相反,我们可以使用.Equals方法和! operator: 操作员:

public bool IsConsistent<T>(Func<Foo, T> property)
  where T : struct
{
  foreach (Foo tempFoo in allFoos)
  {
    if (!property(tempFoo).Equals(property(defaultFoo)))
      return false;
  }
  return true;
}

The where T : struct clause restricts this to value types like int, bool and decimal. where T : struct子句将where T : struct限制为int,bool和decimal等值类型。 In particular it will not work on strings. 特别是它不适用于字符串。 Removing the where constraint allows it to work on strings and other reference types, but creates the possibility of property(tempFoo) being null, which would cause a NullReferenceException when we called .Equals on it. 删除where约束使其可以在字符串和其他引用类型上使用,但会导致property(tempFoo)为null的可能性,当我们在其上调用.Equals时,这将导致NullReferenceException。 So if you remove the value types constraint then you will need to add error handling for this scenario. 因此,如果删除值类型约束,那么您将需要为这种情况添加错误处理。

I'd love to find a way that is more elegant since I'm having to cut and past roughly the same code 20+ times and just change property names. 我想找到一种更优雅的方法,因为我不得不将大约相同的代码剪切和跳过20多次以上,并且只需更改属性名称即可。

Code generators exist for exactly this purpose. 正是出于这个目的而存在代码生成器。 But if you don't want to go that route, you can shorten your code to this: 但是,如果您不想走这条路,可以将代码缩短为:

return allFoos.All(foo => foo.FooVar1 == defaultFoo.FooVar1);

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

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