【问题标题】:How to create properties with "delegated" accessors?如何使用“委托”访问器创建属性?
【发布时间】:2011-08-18 17:27:40
【问题描述】:

我是 c# 的新手,这几天一直对此感到困惑。基本上,我想创建一个 type 属性,并将 getter 和 setter 逻辑委托给该参数所属的基本类型。

这只是一个应用程序:一个属性,其值由注册表或某个配置文件设置。

  • get 上的属性处理程序会执行检查缓存值(或不缓存)等操作,如果未缓存则检索该值,缓存该值(或不缓存)并返回它。
  • 设置器的行为将只允许属性处理程序设置值(如果可能)。

有什么建议吗?我曾考虑过使用DefaultPropertyAttribute,但我不太明白如何不为每个访问器编写所有必要的逻辑。


看起来这就是我想要的:http://www.sharpcrafters.com/postsharp

“少写代码”是的。没关系。

【问题讨论】:

    标签: c# properties metaprogramming accessor


    【解决方案1】:

    我并不以此为荣:

    public abstract class HorribleBaseType
    {
      private Lazy<string> _connectionString;
      private Action<string> _connectionStringSetter;
      private Func<string> _connectionStringGetter;
    
      public HorribleBaseType(
        Func<string> connectionStringGetter, 
        Action<string> connectionStringSetter)
      {
        _connectionStringGetter = connectionStringGetter;
        _connectionStringSetter = connectionStringSetter;
    
        _connectionString = new Lazy<string>(connectionStringGetter);
      }
    
      public string ConnectionString
      {
        get { return _connectionString.Value; }
        set 
        { 
          _connectionStringSetter(value);
          _connectionString = new Lazy<string>(_connectionStringGetter);
        }
      }
    }
    
    public class HorribleType : HorribleBaseType
    {
      public HorribleType()
        : base(() => MyConfiguration.ConnectionString,
               (v) => MyConfiguration.ConnectionString = v) { }
    }
    

    100% 未经测试。

    更新结合使用上述内容和@hunter 的回答,您可以执行以下操作:

    public class DelegateProperty<T>
    {
        #region Fields
        private readonly Func<T> _getter;
        private readonly Action<T> _setter;
        private Lazy<T> _lazy;
        #endregion
    
        #region Constructors
        public DelegateProperty(Func<T> getter, Action<T> setter)
        {
            _getter = getter;
            _setter = setter;
    
            _lazy = new Lazy<T>(getter);
        }
        #endregion
    
        #region Properties
        public T Value
        {
            get { return _lazy.Value; }
            set
            {
                _setter(value);
                _lazy = new Lazy<T>(_getter);
            }
        }
        #endregion
    
        #region Operators
        public static implicit operator T(DelegateProperty<T> prop)
        {
            return prop.Value; 
        }
        #endregion
    }
    

    有了它,您现在可以执行以下操作:

    class Program
    {
        static void Main(string[] args)
        {
            string name = "Matt";
            var prop = new DelegateProperty<string>(
                () => name,
                value => name = value);
    
            var test = new Test(prop);
            Console.WriteLine(test.Name);
    
            test.Name = "Ben";
            Console.WriteLine(name);
    
            Console.ReadKey();
        }
    }
    
    public class Test
    {
        private readonly DelegateProperty<string> NameProperty;
    
        public Test(DelegateProperty<string> prop)
        {
            NameProperty = prop;   
        }
    
        public string Name
        {
            get { return NameProperty; }
            set { NameProperty.Value = value; }
        }
    }
    

    【讨论】:

      【解决方案2】:

      使用这个愚蠢的类:

      public class Property<T>
      {
          Func<T> _func;
          T _value;
          bool _fetched;
      
          public Property(Func<T> func)
          {
              _func = func;
          }
      
          public T Value
          {
              get 
              {
                  if (!_fetched)
                  {
                      _value = _func();
                      _fetched = true;
                  }
                  return _value;
              }
              set { _value = value; }
          }
      }
      

      你可以这样做:

      public class TestClass
      {
          Property<int> _propertyInt;
          public int MyInt
          {
              get { return _propertyInt.Value; }
              set { _propertyInt.Value = value; }
          }
      
          Property<string> _propertyString;
          public string MyString
          {
              get { return _propertyString.Value; }
              set { _propertyString.Value = value; }
          }
      }
      

      当然,这不会处理所有情况,但它可能会让你走上“正确”的轨道……

      【讨论】:

      • 但是你仍然有一个通用的设置器,不受预期行为类型的限制。至少你知道这个想法是不要使用这种行为的基类。尽管来自脚本背景,但我并不完全反对通用二传手的想法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-02
      • 1970-01-01
      • 2020-09-19
      • 2012-06-04
      • 1970-01-01
      相关资源
      最近更新 更多