C#参考文献;隐藏成员
假设您有一个定义如下的类C#参考文献;隐藏成员,c#,oop,friend,double-pointer,C#,Oop,Friend,Double Pointer,假设您有一个定义如下的类 public class SomeClass { public Manager m { get; protected set; } public SpecialData data { get; protected set; } //More methods and member code here... } 我需要我的manager类能够以某种方式更改SpecialData成员的集合引用。我可以用C++中的双指针或朋友类来实现这一点,但
public class SomeClass
{
public Manager m { get; protected set; }
public SpecialData data { get; protected set; }
//More methods and member code here...
}
我需要我的manager类能够以某种方式更改SpecialData成员的集合引用。我可以用C++中的双指针或朋友类来实现这一点,但在C语言中,这个选项是不可用的。如何保护SpecialData不受外部用户设置的影响,同时仍允许Manager类控制设置?我可以用internal关键字来做,但这看起来并不是非常安全或干净
非常感谢您的帮助。如果manager类与
SomeClass
是同一程序集的一部分,使成员内部
可以使同一程序集中的类访问setter:
public SpecialData data { get; protected internal set; }
类似于C++中使用<代码>朋友< /C> >,除了“友情”扩展到同一程序集的所有成员之外。
如果管理器是其他包的一部分,则可以在程序集上使用属性。但是,在这种情况下,您应该对扩展友谊的程序集进行签名,以避免试图从未经授权的代码访问setter。创建一个继承
SomeClass
的类,该类的外观如下:
internal class SomeClassDecorator : SomeClass
{
public void SetSpecialData(SpecialData value)
{
data = value;
}
}
受保护意味着它可用于类的派生,并且由于
SomeClass
不是密封的,因此您可以简单地从它派生并执行任何需要的操作。然后可以使用此装饰器,而不是SomeClass
本身。而且,您可以拥有所需的任意数量的装饰器,每个装饰器处理其特殊的SpecialData
它可能并不完全是您想要的,但是所描述的internal
关键字可以控制同一程序集中的访问;与C++中的<代码>朋友< /Cord>关键字类似。可以使属性<代码>内部< /代码>。这将使属性仅在同一程序集中可见。或者,您可以使用内部visibletoAttribute
来允许特定程序集访问该属性
另一种方法是使用接口隐藏该属性:
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...
}
这样,数据
只能从接口引用中看到
所以这不起作用:
SomeClass c = new SomeClass();
c.data;
但这确实:
ISomeClass c = new SomeClass();
c.data;
在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;
}
}
公共类SomeClass
{
私人经理;;
公共经理
{
获取{return\m}
设置
{
//注册/取消注册财产转让事件
如果(_m!=null)
_m、 RequestChangeSpecialData-=RequestChangeSpecialData;
_m=值;
如果(_m!=null)
_m、 RequestChangeSpecialData+=RequestChangeSpecialData;
}
}
公共特殊数据数据{get;private set;}
私有无效请求ChangeSpecialData(对象发送方,ChangeSpecialDataEventArgs e)
{
//设置新的引用
数据=e.SpecialData;
}
}
公共班级经理
{
公共无效剂量测定法()
{
//manager类想要做一些事情,并且想要更改SpecialData实例..,因此它触发事件RequestChangeSpecialData
SpecialData=新的SpecialData();
//如果事件已绑定。
if(RequestChangeSpecialData!=null)
RequestChangeSpecialData(此,新的ChangeSpecialDataEventArgs(数据));
}
公共事件事件处理程序RequestChangeSpecialData;
}
公共类ChangeSpecialDataEventArgs:EventArgs
{
公共特殊数据数据{get;private set;}
公共更改SpecialData事件参数(SpecialData数据)
{
数据=数据;
}
}
未经测试(写在记事本中)
现在,Manager
可以更改SpecialData
属性。这样,管理器就不依赖于SomeClass
/接口或程序集。您能解释一下为什么认为内部
不安全或不干净吗?你的意思是说它在一般情况下是这样的,还是说它不适合你的具体设计?我会说这是一个完美的解决方案,尽管说实话,我不知道你为什么要这么做。我确实提到了内部关键字。我知道这是一个选择,但这是一个好的选择吗?我担心有人认为这可能是一个设计缺陷。如果没有,这肯定会奏效。这是一个大项目,所以将它们结合在一起可能是一个大问题…@user3812869是的,internal
是一个不错的选择。它是为这样的情况而设计的,当您设计一个共享内部表示知识的相关类包时。NET采取预防措施,不将这些知识泄露到您的库之外。想必,没有办法保护您的代码不受那些可以修改您的程序集的人的攻击。在这种情况下,我将尝试解决这些问题。我觉得这个设计有点奇怪。实际上,我有一个状态管理器和一个包含在游戏对象中的精灵。StateManager包含状态。这些状态需要编辑Sprite字段。@user3812869最后一位听起来确实有点奇怪,因为它听起来像Sprite
是视觉表示的一部分,而其他一切都是模型的一部分。您最好更改排序的精灵标识符,并将它们“链接”到视图级别上的sprite
对象。但这不会改变您在类中设置可访问性的方式,但是.was即将发布事件选项