C# 内部全局属性..臭味?
我在编写一些代码时遇到了一些设计问题: 我的基本代码如下所示: 主COM包装器:C# 内部全局属性..臭味?,c#,design-patterns,com,word-wrap,C#,Design Patterns,Com,Word Wrap,我在编写一些代码时遇到了一些设计问题: 我的基本代码如下所示: 主COM包装器: public class MapinfoWrapper { public MapinfoWrapper() { Publics.InternalMapinfo = new MapinfoWrapper(); } public void Do(string cmd) { //Call COM do command } pu
public class MapinfoWrapper
{
public MapinfoWrapper()
{
Publics.InternalMapinfo = new MapinfoWrapper();
}
public void Do(string cmd)
{
//Call COM do command
}
public string Eval(string cmd)
{
//Return value from COM eval command
}
}
public class TableInfo
{
public string Name {
get { return Publics.InternalMapinfo.Eval("String comman to get the name"); }
set { Publics.InternalMapinfo.Do("String command to set the name"); }
}
}
公共静态类保存对包装器的内部引用:
internal static class Publics
{
private static MapinfoWrapper _internalwrapper;
internal static MapinfoWrapper InternalMapinfo
{
get
{
return _internalwrapper;
}
set
{
_internalwrapper = value;
}
}
}
使用内部包装器实例的代码:
public class MapinfoWrapper
{
public MapinfoWrapper()
{
Publics.InternalMapinfo = new MapinfoWrapper();
}
public void Do(string cmd)
{
//Call COM do command
}
public string Eval(string cmd)
{
//Return value from COM eval command
}
}
public class TableInfo
{
public string Name {
get { return Publics.InternalMapinfo.Eval("String comman to get the name"); }
set { Publics.InternalMapinfo.Do("String command to set the name"); }
}
}
有人觉得这很难闻吗?我应该使用内部属性来保存对主包装器对象的引用,还是应该在这里使用不同的设计
注意:MapInfo包装器对象将由外部世界使用,因此我不想将其作为一个单独的对象。不将MapInfo包装器注入类本身会降低TableInfo类的可测试性。是否使用这些MapInfo包装类的全局缓存取决于该类——您需要决定是否有必要,但将包装传递到TableInfo并在那里使用它,而不是直接在TableInfo方法中引用全局副本,这将改进您的设计。结合接口的定义(即“重构到接口”)执行此操作 我还将在Publics的getter中进行延迟实例化,以确保该对象在尚未创建时可用,而不是在MapInfoWrapper的构造函数中进行设置
public class TableInfo
{
private IMapinfoWrapper wrapper;
public TableInfo() : this(null) {}
public TableInfo( IMapinfoWrapper wrapper )
{
// use from cache if not supplied, could create new here
this.wrapper = wrapper ?? Publics.InternalMapInfo;
}
public string Name {
get { return wrapper.Eval("String comman to get the name"); }
set { wrapper.Do("String command to set the name"); }
}
}
public interface IMapinfoWrapper
{
void Do( string cmd );
void Eval( string cmd );
}
public class MapinfoWrapper
{
public MapinfoWrapper()
{
}
public void Do(string cmd)
{
//Call COM do command
}
public string Eval(string cmd)
{
//Return value from COM eval command
}
}
internal static class Publics
{
private static MapinfoWrapper _internalwrapper;
internal static MapinfoWrapper InternalMapinfo
{
get
{
if (_internalwrapper == null)
{
_internalwrapper = new MapinfoWrapper();
}
return _internalwrapper;
}
}
}
现在,当您测试TableInfo方法时,您可以通过向构造函数提供自己的实现来轻松模拟MapInfo包装器。Ex(假设是手模拟):
我曾考虑将此添加到我的原始回复中,但这确实是一个不同的问题。
如果您存储并使用缓存的副本,您可能需要考虑MAPIFOWRAPPER类是否需要线程安全。无论何时使用单个、全局副本,都需要考虑它是否会同时被多个线程使用并构建它,以便任何关键部分(任何地方的数据都可能被改变或必须假设不改变)是线程安全的。如果必须支持多线程环境(比如在网站中),那么这可能会反对使用单个全局副本,除非创建类的成本非常高。当然,如果您的类依赖于其他也不是线程安全的类,那么您可能需要使您的类始终是线程安全的。
酷,我本来打算这样做的,但我认为这可能是错误的,但现在我看到它是通过测试实现的,这使堆更有意义。为此干杯!我唯一的问题是,从用户的角度来看,它读起来并不好。我不确定我是否喜欢这样:TableInfo选项卡=新建TableInfo(无);