用于从子组件类中访问拥有类的代码模式(朋友接口?)

时间:2014-08-14 13:34:24

标签: c# design-patterns interface friend

如果我有一个类(P类)使用其他一些可重用的组件(C类)(例如状态管理器),那么如果该组件需要访问我的顶级类(P)中的一些数据那么我有什么选择?

关键是我不希望将这些数据暴露给外界,只是在我知道并信任并在P中使用的组件中。

public static class Program
{
    private void Main()
    {
        var owner = new Owner();

        // I can call Foo()!!!
        ((IOwner)owner).Foo();
    }
}


public interface IOwner
{
    void Foo();
}

public class Owner : IOwner
{
    private Component m_component;

    public void SomeExternalAPI()
    {
        m_component = new Component(this);
        m_component.DoSomething();
    }

    void IOwner.Foo()
    {
        // do something
    }
}

public class Component
{
    private readonly IOwner m_owner;

    public Component(IOwner owner)
    {
        m_owner = owner;
    }

    public void DoSomething()
    {
        m_owner.Foo();
    }
}

我可以在P上使用接口,但这会在外部公开数据。 我可以在P上使用显式接口,但这可以是强制转换,因此也很容易公开数据。

如果我可以以某种方式传授"友谊"在组件(我创建,理想情况下在实例级别!)上,并使IOwner成为仅限朋友的界面,它将是安全的。

我知道目前在C#中这是不可能的。

它经常出现在我身上。

有没有人有任何解决方案或建议?

2 个答案:

答案 0 :(得分:0)

您可以在界面和internal课程中使用Component访问者。

internal interface IOwner
{
     void Foo();
}

internal class Component
{
     private readonly IOwner m_owner;

     public Component(IOwner owner)
     {
          m_owner = owner;
     }

     public void DoSomething()
     {
          m_owner.Foo();
     }
}

Owner课程为public

public class Owner : IOwner
{
    private Component m_component;

    public void SomeExternalAPI()
    {
         m_component = new Component(this);
         m_component.DoSomething();
    }

    void IOwner.Foo()
    {
         // do something
    }
}

使用这种方法,将无法从外部程序集

访问界面和Component类

客户只会看到 Owner类及其SomeExternalAPI()方法。

var Owner = new Owner();
owner.SomeExternalAPI();
//owner.Foo() --> Won't compile!
//((IOwner)owner).Foo() --> Won't compile!

答案 1 :(得分:0)

我认为我找到了一个合理的解决方案,尽管它的工作非常辛苦,代码比我想要的还要多

使用代理类,它实现了公共IOwner接口,但是可以使用内部的IInternalOwner接口调用实际所有者,该接口是在构造时给出的。

然后,代理就像一个令牌,允许所有者为其提供此令牌的人调用。它的代码比我想要的多,如果将它构建到C#中会很好: - )。

但是,它在程序集之间起作用(实际上我有4个来测试它!)。

public class Owner : IInternalOwner
{
    private ITheComponent m_component;

    public void SomeExternalAPI()
    {
        var proxy = new Proxy(this);
        m_component = ClassFactory.ConstructTheComponent(proxy);
        m_component.DoSomething();
    }

    void IInternalOwner.Foo()
    {
        // do something
        Console.WriteLine("Owner.Foo was called");
    }

    private class Proxy : IOwner
    {
        private IInternalOwner m_owner;

        public Proxy(IInternalOwner owner)
        {
            m_owner = owner;
        }

        /// <summary>
        /// pass through for each method & property!
        /// </summary>
        public void Foo()
        {
            m_owner.Foo();
        }
    }


}

internal interface IInternalOwner
{
    void Foo();
}