0

私は C++ のフレンドシップ機能がとても気に入っています。親と子がいるとしましょう。子の ctor は、Parent をパラメーターとして受け取ります。

Child::Child(Parent & parent)
{
    // Parent::RegisterChild is private
    parent.RegisterChild(this);
}

友情のおかげで、親と子は自分自身に対して非常に安全な制御を維持できます。たとえば、子が親を変更した場合、以前の親に子リストから切り離されたいことを通知し、新しい親に結合したいことを通知する場合があります。そのリストに。このソリューションのセキュリティは、Parent または Child から派生するクラスがこのメカニズムを破らないことを意味します。

残念ながら、C# にはフレンドシップなどの機能はありません。アクセス修飾子がありますがinternal、クラス要素の可視性をアセンブリに制限するため、アセンブリを拡張して新しいクラスを導入すると、メカニズムは安全ではなくなります。そして、セキュリティを提供するためだけに、そのようなクラスを個別のアセンブリに抽出することは、非常に厄介な考えのようです。

既存の C# メカニズムを使用して、派生クラスで破ることができない 2 つのクラス間でこのような緊密で安全な連携を提供する方法はありますか?


編集:コメントに応じて

エリックが述べたように、ソースコードにアクセスできる人はいつでもそれを破ることができるため、これは信頼の問題ではありません(プライベート修飾子を削除する、別のフレンドクラスを追加するなど)。これは、後で追跡するのが困難な単純でばかげた間違いを人々が犯すのを防ぐために設計されたセキュリティ対策です。私はフレンドを使用して、基本クラスに埋め込まれた分離されたメカニズムを作成します。これは、派生クラスでは破ることができません (または少なくとも簡単にはできません)。そうすれば、私も同僚もこれらについて心配する必要がなくなります。

4

2 に答える 2

0

これが私のプロジェクトに実装したものの基本的な考え方であり、これはうまく機能します。うまくいけば、それもあなたにとってもうまくいくでしょう。これは、実行時にのみフレンドシップを強制することに注意してください (これは良く聞こえません)。

public interface IFriendKey { object Id {get; set;} }

class Friend<TFriend>
{
    protected void FriendAssert(IFriendKey key)
    {
        if ( key == null || key.Id == null || key.Id.GetType() != typeof(TFriend) )
            throw new Exception("No right to execute the called method.");
    }
}

class A : Friend<B>
{
    public void f(IFriendKey key)
    {
        FriendAssert(key);
        Console.WriteLine("ONLY class B can execute this method successfully, even though it is declared public.");
    }
}

class B
{
    private class AFriendKey : IFriendKey 
    {
        public object Id {get; set;}
    }

    IFriendKey Key { get { return new AFriendKey() {Id = this}; } }

    public void g()
    {
        new A().f(this.Key); 
    }
}

public class Test
{
    public static void Main()
    {
        new B().g();
    }
}

オンラインデモ

それが役立つことを願っています。

于 2013-10-08T07:18:12.183 に答える