Как создать свойства с «делегированными» аксессорами? - PullRequest
3 голосов
/ 04 мая 2011

Я новичок в c # и ломаю голову над этим пару дней.По сути, я хочу создать свойство type с логикой getter и setter, делегированной базовому типу, которому принадлежит этот параметр.

Это просто одно приложение: свойство, значение которого задается, скажем, реестром или каким-либо файлом конфигурации.

  • Обработчик свойства при получении будет делать что-то вроде проверки кэшированного значения (или нет), получения значения, если оно не кэшировано, кэширования значения (или нет) и его возврата.
  • Поведение для установщика позволит только обработчику свойств устанавливать значение (если возможно).

Есть предложения?Я думал об использовании DefaultPropertyAttribute, но не могу понять, как не написать всю логику, необходимую для каждого метода доступа.


Похоже, это то, что я хочу: http://www.sharpcrafters.com/postsharp

"Пишите меньше кода" Да.Все в порядке.

Ответы [ 2 ]

2 голосов
/ 04 мая 2011

Я не горжусь этим:

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% не проверено.

ОБНОВЛЕНИЕ Используя комбинацию вышеупомянутого и ответ @ охотника, выможет сделать что-то вроде:

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; }
    }
}
1 голос
/ 04 мая 2011

Используя этот тупой класс:

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

Конечно, это не подходит для каждого случая, но может привести вас к "правильному" следу ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...