从子组件类(友接口?)中访问所属类的代码模式

本文关键字:访问 代码 模式 组件 接口 | 更新日期: 2023-09-27 18:17:56

如果我有一个类(类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#中这是不可能的。

这对我来说是很常见的。

谁有什么解决方案或建议?

从子组件类(友接口?)中访问所属类的代码模式

您可以在您的接口和Component类上使用internal访问器

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!

我想我已经找到了一个合理的解决方案,尽管它相当辛苦,而且代码比我想的要多

使用代理类,它实现公共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();
}