C#参考文献;隐藏会员

时间:2014-09-18 14:20:58

标签: 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...
}

我需要我的经理类以某种方式能够更改SpecialData成员的集合引用。我可以使用C ++中的双指针或朋友类来完成此操作,但遗憾的是,该选项在C#中不可用。如何保持SpecialData不受外部用户设置,同时仍允许Manager类控制设置?我可以用内部关键字做到这一点,但这看起来并不安全或干净......

非常感谢任何帮助。

5 个答案:

答案 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;