想象一下,你有一个如下定义的类。
public class SomeClass
{
public Manager m { get; protected set; }
public SpecialData data { get; protected set; }
//More methods and member code here...
}
我需要我的经理类以某种方式能够更改SpecialData成员的集合引用。我可以使用C ++中的双指针或朋友类来完成此操作,但遗憾的是,该选项在C#中不可用。如何保持SpecialData不受外部用户设置,同时仍允许Manager类控制设置?我可以用内部关键字做到这一点,但这看起来并不安全或干净......
非常感谢任何帮助。
答案 0 :(得分:4)
如果manager类与SomeClass
属于同一个程序集,那么使成员internal
可以使同一程序集中的类可以访问setter:
public SpecialData data { get; protected internal set; }
这与在C ++中使用friend
类似,只是“友谊”扩展到同一程序集的所有成员。
如果经理是其他包的一部分,您可以在程序集上使用InternalsVisibleTo
属性。但是,在这种情况下,您应该为扩展友谊的程序集签名,以避免尝试从未经授权的代码访问setter。
答案 1 :(得分:3)
如何在Manager
课程中创建活动,例如RequestChangeSpecialData
个活动。 Manager
会触发事件,SomeClass
会更改SpecialData
个实例。
public class SomeClass
{
private Manager _m;
public Manager M
{
get { return _m}
set
{
// register/unregister event on property assignment
if(_m != null)
_m.RequestChangeSpecialData -= RequestChangeSpecialData;
_m = value;
if(_m != null)
_m.RequestChangeSpecialData += RequestChangeSpecialData;
}
}
public SpecialData Data { get; private set; }
private void RequestChangeSpecialData(object sender, ChangeSpecialDataEventArgs e)
{
// set the new reference
Data = e.SpecialData;
}
}
public class Manager
{
public void DoSomething()
{
// the manager class wants to do something, and wants to change the SpecialData instance.., so it fires the event RequestChangeSpecialData
SpecialData data = new SpecialData();
// if the event is bound.
if(RequestChangeSpecialData != null)
RequestChangeSpecialData(this, new ChangeSpecialDataEventArgs(data));
}
public event EventHandler<ChangeSpecialDataEventArgs> RequestChangeSpecialData;
}
public class ChangeSpecialDataEventArgs : EventArgs
{
public SpecialData Data {get; private set; }
public ChangeSpecialDataEventArgs(SpecialData Data)
{
Data = data;
}
}
UNTESTED (写在记事本中)
现在Manager
能够更改SpecialData
属性。这样管理器不依赖于SomeClass
/接口或程序集。
答案 2 :(得分:1)
创建一个继承SomeClass
的类,看起来像这样:
internal class SomeClassDecorator : SomeClass
{
public void SetSpecialData(SpecialData value)
{
data = value;
}
}
受保护意味着它可以被类的衍生物使用,并且由于SomeClass
没有被密封,你可以简单地从它派生并做你需要的任何事情。然后,您可以使用此装饰器而不是SomeClass
本身。此外,您可以根据需要拥有尽可能多的装饰器,每个装饰器都处理其特殊的SpecialData
。
答案 3 :(得分:1)
它可能不完全是您要查找的内容,但internal
描述的friend
关键字可以控制同一程序集中的访问权限;它看起来与C ++中{{1}}关键字的目的相似。
答案 4 :(得分:1)
您可以创建属性internal
。这将使该属性仅在同一个程序集中可见。 (可选)您可以使用InternalsVisibleToAttribute
来允许特定程序集访问该属性。
另一种方法是使用interface
隐藏该属性:
public interface ISomeClass
{
Manager m { get; }
SpecialData data { get; set; }
}
public class SomeClass : ISomeClass
{
public Manager m { get; protected set; }
SpecialData ISomeClass.data { get; set; }
//More methods and member code here...
}
通过这种方式,data
仅在界面参考中可见。
所以这不起作用:
SomeClass c = new SomeClass();
c.data;
但这样做:
ISomeClass c = new SomeClass();
c.data;