装饰属性

时间:2014-06-26 12:14:24

标签: c#

我想"装饰"我自己的对象的属性。比方说,我想知道调用getter的次数,setter花了多长时间,记录任何新的值...

我试图尽可能简化这一点。理想的解决方案可能使用属性,它可能如下所示:

public class MyClass
{
    [CountGetterCalls]
    [LogSettingValue]
    public int SomeProperty;
}

我没有成功实现这个,作为一个解决方案,我尝试了一种属性包装器。但这远非完美。你的方法是什么?

public class MyClass
{
    public MyClass()
    {
        SomeProperty = new PropertyWrapper<int>(new CountCallsPropertyDecorator<int>(new LogSettingPropertyDecorator<int>(new NullDecorator<int>())));
    }

    public PropertyWrapper<int> SomeProperty;
}

public interface IPropertyDecorator<T>
{
    void OnGetValue();
    void OnSetValue(T value);
}

public class PropertyWrapper<T>
{
    private readonly IPropertyDecorator<T> _decorator;
    private T _value;

    public PropertyWrapper(IPropertyDecorator<T> decorator)
    {
        _decorator = decorator;
    }

    public T Value
    {
        get
        {
            _decorator.OnGetValue();
            return _value;
        }
        set
        {
            _decorator.OnSetValue(value);
            _value = value;
        }
    }
}

public class CountCallsPropertyDecorator<T> : IPropertyDecorator<T>
{
    private readonly IPropertyDecorator<T> _decorator;
    private int _nbGetCalled;
    private int _nbSetCalled;

    public int NbGetCalled { get { return _nbGetCalled; } }
    public int NbSetCalled { get { return _nbSetCalled; } }

    public CountCallsPropertyDecorator(IPropertyDecorator<T> decorator)
    {
        _decorator = decorator;
    }

    public void OnGetValue()
    {
        _decorator.OnGetValue();
        _nbGetCalled++;
    }

    public void OnSetValue(T value)
    {
        _decorator.OnSetValue(value);
        _nbSetCalled++;
    }
}

public class LogSettingPropertyDecorator<T> : IPropertyDecorator<T>
{
    private readonly IPropertyDecorator<T> _decorator;

    public LogSettingPropertyDecorator(IPropertyDecorator<T> decorator)
    {
        _decorator = decorator;
    }

    public void OnGetValue() { _decorator.OnGetValue(); }
    public void OnSetValue(T value)
    {
        _decorator.OnSetValue(value);
        Console.WriteLine("Property called.");
    }
}

public class NullDecorator<T> : IPropertyDecorator<T>
{
    public void OnGetValue() { }

    public void OnSetValue(T value) { }
}

1 个答案:

答案 0 :(得分:2)

在.net中,方法“装饰”不能像其他语言一样工作(例如Python),属性的存在不会改变方法的行为,只会改变其元数据。元数据可用于通过其他工具更改其行为。

您需要和AOP框架(如专有PostSharp)或动态代理生成器(如LinFuCastle)来实现您想要的目标。

两者都有他的优点和缺点,看看每一个。