5

假设您有一个定义如下的类。

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 类控制设置?我可以使用 internal 关键字来做到这一点,但这似乎并不安全或干净......

任何帮助是极大的赞赏。

4

5 回答 5

4

如果管理器类是与 相同的程序集的一部分,则SomeClass使该成员internal可以使同一程序集中的类可以访问设置器:

public SpecialData data { get; protected internal set; }

这类似于friend在 C++ 中的使用,不同之处在于“友谊”扩展到同一程序集的所有成员。

如果管理器是不同包的一部分,则可以InternalsVisibleTo在程序集上使用属性。但是,在这种情况下,您应该签署您扩展友谊的程序集,以避免尝试从未经授权的代码访问设置器。

于 2014-09-18T14:23:36.653 回答
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;
    }
}

未经测试(写在记事本中)

现在Manager可以更改SpecialData属性。这样,管理器不依赖于SomeClass/interface 或程序集。

于 2014-09-18T14:28:36.300 回答
1

创建一个继承SomeClass并看起来像这样的类:

internal class SomeClassDecorator : SomeClass
{
    public void SetSpecialData(SpecialData value)
    {
        data = value;
    }
}

受保护意味着它可用于类的派生类,并且由于SomeClass不是密封的,因此您可以简单地从它派生并做任何您需要的事情。然后你可以使用这个装饰器而不是SomeClass它本身。此外,您可以拥有尽可能多的装饰器,每个装饰器都处理其特殊的SpecialData.

于 2014-09-18T14:23:36.843 回答
1

它可能不是您要查找的内容,但此处internal描述的关键字可以控制同一程序集中的访问;它的目的似乎与C++ 中的关键字相似。friend

于 2014-09-18T14:23:56.690 回答
1

你可以做财产internal。这将使该属性仅在同一程序集中可见。或者,您可以使用InternalsVisibleToAttribute允许特定程序集访问该属性。

另一种方法是使用 aninterface来隐藏该属性:

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;
于 2014-09-18T14:24:45.783 回答