【问题标题】:Two questions about properties in C#关于C#中属性的两个问题
【发布时间】:2011-02-16 14:25:57
【问题描述】:

我有两个简单的问题,基于我正在扩展现有类的事实......

1) 我正在实现一些自定义属性,并且我希望每当它们的值更改时调用特定的(无参数)函数。当然,如果不需要调用该函数,我可以使用传统的{ get; set; } 语法而无需额外的变量。但是,即使我在 set 访问器中修改的唯一内容是对另一个函数的调用,我也必须声明一个私有变量,以便我可以自己指定 get 和 set 访问器......没有声明这么多变量的更简单的方法吗?不是有类似一般“财产变更”事件吗?

2) 由于我要覆盖 .NET 用户控件,因此我想更改一些基本属性出现在其下的类别。目前,为了使用[Category("")] 语法,我必须将这些属性声明为new 并实现get 和set 引用基类的属性。没有简单的方法吗?

【问题讨论】:

    标签: c# properties


    【解决方案1】:

    也许您应该查看INotifyPropertyChanged 接口。下面是一些使用它的示例代码。我使用这个接口来完成 WPF 中的数据绑定。您可以处理该事件,发现已更改的属性并采取相应措施。如果您希望设置器是异步的,您甚至可以在另一个线程 (PropertyChanged.BeginInvoke()) 上引发事件...

    using System;
    using System.ComponentModel;
    
    public class Foo : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        private string _name;
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }
    }
    

    【讨论】:

    • 他问是否可以在不需要重新定义整个属性的情况下引发此方法/事件。
    • 我明白这一点,其他人已经指出 C# 不支持它。我只是提供了一个关于 C# 如何支持通知更改属性的机制的答案。这可能不是他正在寻找的神奇答案,但它可能很有用。
    【解决方案2】:

    C# 本身不支持此功能,但您可以通过Interceptors in Windsor 进行 AOP,这将在运行时为您提供帮助,或者使用 PostSharp 之类的东西来生成事件调用的代码。 PostSharp 将在创建程序集后注入 IL 代码,因此它在运行时不会像 Windsor 那样对性能造成太大影响。

    阅读更多关于AOP 的信息也是一个好主意。

    【讨论】:

      【解决方案3】:

      如果您试图在没有大量重复编码的情况下从访问的属性中捕获事件,同时保持关注点分离,那么您可以使用诸如 Castle 之类的框架研究面向方面的编程技术,但要注意这是一个复杂的包含有关您的应用程序架构的艰难选择的主题。

      【讨论】:

        【解决方案4】:

        1) 不,没有属性更改事件。如果您坚持不创建额外变量you could go the AOP route。如果没有 AOP,您应该会感到满意,除非您正在处理无数的属性,在这种情况下,您可以选择代码生成(可能编写 python/ruby 脚本来生成代码或使用通用代码生成器)

        2) 我认为您不能在不生成代码的情况下更改运行前的属性(在 Visual Studio 中)。

        【讨论】:

          【解决方案5】:

          也许我不在了,但是对于 #1 来说这样的事情怎么样:

          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Text;
          
          namespace EraseMe2
          {
          class Program
          {
              static void Main(string[] args)
              {
                  Test t = new Test();
                  t.MyProperty = 100;
                  t.MyProperty = 500;
              }
          }
          
          
          class Test
          {
              public int set(ref int prop, int val)
              {
                  prop = val;
                  Console.WriteLine(String.Format("{0} changed to {1}", prop.GetType().Name, val.ToString()));
                  return val;
              }
          
              private int _myProperty;
              public int MyProperty
              {
                  get { return _myProperty; }
                  set
                  {
                      _myProperty = set(ref _myProperty, value);
                  }
              }
          }
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-03-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-28
            相关资源
            最近更新 更多