接口上的只读属性可在PropertyGrid中编辑

我有一个带有一堆属性的接口,其中一些被定义为readonly,例如:

public interface IActivity {
  string Id { get; }
  bool IsEnabled { get; }
}

实现此接口的类具有公共 set 方法,供其他地方使用,但此接口的使用者不应该能够设置这些属性 . 我使用公共集合方法绑定到类,只要消费者应该关注的属性是可在网格内编辑的 .

我可以通过两种方式解决这个问题,首先是通过制作setter internal ,或者通过使用 [ReadOnly] 属性标记属性,但是这似乎不是"right",因为理论上其他东西可以实现我的控制之外的这个接口,那些据说只读属性然后可以通过属性网格更改 .

在将对象分配给属性网格时,我尝试显式转换为接口,但这也没有帮助:

propGrid.SelectedObject = (IActivity)obj;

有没有办法强制PropertyGrid控件尊重接口的 Contract ,而不是必须更改具体类?

回答(2)

2 years ago

我通过创建一个完全匹配接口规范的包装类来解决这个问题:

class ActivityWrapper : IActivity {
    private readonly IActivity _activity;
    public ActivityWrapper(IActivity activity) {
        _activity = activity;
    }

    public string Id
    {
        get { return _activity.Id; }
    }
    public bool IsEnabled
    {
        get { return _activity.IsEnabled; }
    }
}

在将对象暴露给属性网格时使用它:

propGrid.SelectedObject = new ActivityWrapper((IActivity)obj);

如果有一种不同的,更自动的方式来实现这一点,我仍然感兴趣,而不是维持另一个类 .

2 years ago

詹姆斯的回答是正确的 . 我将补充一点,如果您的IActivity实现了INotifyPropertyChanged,您必须以这样的方式路由事件:

class ActivityWrapper : IActivity
{
    private readonly IActivity _activity;
    public ActivityWrapper(IActivity activity)
    {
        _activity = activity;
        _activity.PropertyChanged += _activity_PropertyChanged;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    void _activity_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, e);
    }

    public string Id
    {
        get { return _activity.Id; }
    }
    public bool IsEnabled
    {
        get { return _activity.IsEnabled; }
    }
}

我看到自动执行此操作的唯一方法是使用Reflection.Emit生成此包装器 .