我有一个带有一堆属性的接口,其中一些被定义为只读,例如:
public interface IActivity {
string Id { get; }
bool IsEnabled { get; }
}
实现此接口的类具有公共set
方法,以供在其他地方使用,但此接口的使用者不应该能够设置这些属性。我现在正在构建一个测试使用者,并通过PropertyGrid控件公开该对象。因为它使用公共集合方法绑定到类,所以对于消费者应该关注的属性是可在网格内编辑的。
我可以通过两种方式解决此问题,首先是制作setter internal
,或者使用[ReadOnly]
属性标记属性,但这似乎并不“正确”,因为理论上其他东西可以实现我的控制之外的那个接口,那些所谓的只读属性然后可以通过属性网格更改。
我在将对象分配给属性网格时尝试显式转换为接口,但这也没有帮助:
propGrid.SelectedObject = (IActivity)obj;
有没有办法强制PropertyGrid控件尊重接口的合约,而不是必须更改具体的类?
答案 0 :(得分:1)
我通过创建一个与接口规范完全匹配的包装类来解决这个问题:
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);
如果有一种不同的,更自动的方法来实现这一点,我仍然感兴趣,而不是维持另一个班级。
答案 1 :(得分:1)
詹姆斯的回答是正确的。我将补充一点,如果你的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生成此包装器。