Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 内部全局属性..臭味?_C#_Design Patterns_Com_Word Wrap - Fatal编程技术网

C# 内部全局属性..臭味?

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

我在编写一些代码时遇到了一些设计问题:

我的基本代码如下所示:

主COM包装器:

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(无);