从子组件类(友接口?)中访问所属类的代码模式
本文关键字:访问 代码 模式 组件 接口 | 更新日期: 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();
}