【发布时间】:2020-01-04 19:33:46
【问题描述】:
下面的示例代码更好地解释了我的问题,它在 cmets 中得到了很好的解释。 Browser 包含 BrowserModule 的各种实现者,这些模块具有对所有者 Browser 的引用,因此它们可以在内部协同工作。每个“主”模块内部都有一个 SpecificModule,这些“主”模块仅充当将实现目标浏览器自动化库(如 Selenium 或 Puppeteer 等)的特定模块的代理......
例如,对于 BrowserMouse 模块,它将 SpecificModule 实例化为 BrowserPuppeteerChromiumSpecificMouse 并将调用委托给该特定模块。
我不希望 Browser 类的用户能够访问每个自动化库的底层实现,所以我以这种方式隐藏它们,但我遇到了问题,例如鼠标位置可能是通过执行 Browser.Mouse.PositionOnDocument = new Point(123,123) 设置,我希望该功能仅在内部(命名空间级别)可用,而不是对库的最终用户可用。
应该允许例如,另一个模块想要改变鼠标的位置,它可以正常改变它,只需访问 Browser.Mouse.PositionOnDocument = new Point();
但这应该只允许来自同一个命名空间,不能来自外部使用,外部使用应该是只读的。
using System;
using System.Drawing;
namespace Test
{
using InternalNamespace;
class Program
{
public static void Main()
{
Browser browser = new Browser();
browser.Initialize();
Console.WriteLine(browser.Mouse.PositionOnDocument);
// This should NOT be allowed because its being used from outside the Browser namespace
browser.Mouse.PositionOnDocument = new Point(2, 2);
Console.WriteLine(browser.Mouse.PositionOnDocument);
}
}
}
namespace InternalNamespace
{
public class Browser
{
public BrowserMouse Mouse;
public void Initialize()
{
// Instantiate the main mouse with underlying specific puppeteer module
// pass a null module to the specific module because it doesnt need
// one underlying specific module
Mouse = new BrowserMouse(this, new BrowserPuppeteerChromiumSpecificMouse(this, null));
// This is OK because its inside the namespace
Mouse.PositionOnDocument = new Point(1, 1);
}
}
public class BrowserModule
{
// ExternalBrowser that owns this module.
protected Browser Browser { get; set; }
// Underlying specific module => Puppeteer, Selenium or anything.
protected BrowserModule SpecificModule { get; set; }
public BrowserModule(Browser browser, BrowserModule specificModule)
{
Browser = browser;
if (specificModule != null)
SpecificModule = specificModule;
}
}
interface ILocatable
{
Point PositionOnDocument { get; set; }
}
// This whole class just servers as a proxy for the underlying module.
public class BrowserMouse : BrowserModule, ILocatable
{
public BrowserMouse(Browser browser, BrowserModule specificModule) : base(browser, specificModule)
{
}
// This delegates the call to the specific module.
public Point PositionOnDocument
{
get
{
return ((ILocatable)SpecificModule).PositionOnDocument;
}
set
{
((ILocatable)SpecificModule).PositionOnDocument = value;
}
}
}
// The specific module implementation that is gonna be called from the main module.
public class BrowserPuppeteerChromiumSpecificMouse : BrowserModule, ILocatable
{
public BrowserPuppeteerChromiumSpecificMouse(Browser browser, BrowserModule specificModule) : base(browser, specificModule)
{
}
public Point PositionOnDocument { get; set; }
}
}
【问题讨论】:
-
你控制界面吗?
-
V0ldek 之所以问这个问题是因为如果您控制界面,您可以删除属性的
set;部分使其成为只读。 -
是的,我愿意。但是,如果我删除了 setter,我需要在该接口的每个实现者中创建一个支持字段,对吗?
-
@Joso Vitor 不,从 C#6 开始支持仅获取自动属性
-
@V0ldek 好吧,实现者特定的类将需要改变这个位置,如果属性是 get 只有我需要一个由这些特定类设置的字段
标签: c# module interface polymorphism public