Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.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#_Constructor - Fatal编程技术网

C# 在类构造函数中初始化什么最好?

C# 在类构造函数中初始化什么最好?,c#,constructor,C#,Constructor,我有一个关于建设者的设计问题。在google上看了这篇关于“干净代码对话”的文章后,他谈到了初始化类的重要性,以及构造函数中的更多内容,以及更好的测试选项。例如,在我的代码中,我在服务svc构造函数中的iis上托管了一个wcf服务,我们初始化了整个服务 BService() { if (!m_DAL.Initilaze()) { throw new Exception("Due to problems in the initial

我有一个关于建设者的设计问题。在google上看了这篇关于“干净代码对话”的文章后,他谈到了初始化类的重要性,以及构造函数中的更多内容,以及更好的测试选项。例如,在我的代码中,我在服务svc构造函数中的
iis
上托管了一个wcf服务,我们初始化了整个服务

 BService()
    {
        if (!m_DAL.Initilaze())
        {
            throw new Exception("Due to problems in the initialization B2BService is down");
        }

        m_sBadTransactionDir = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "BadTransaction";

        _address1 = new EndpointAddress(System.Configuration.ConfigurationManager.AppSettings["1Address"]);
        _address2 = new EndpointAddress(System.Configuration.ConfigurationManager.AppSettings["2Address"]);
        _address3 = new EndpointAddress(System.Configuration.ConfigurationManager.AppSettings["3Address"]);
        _address4 = new EndpointAddress(System.Configuration.ConfigurationManager.AppSettings["4Address"]);

        LoadSitesFromAdaptors();

        double interval1= Convert.ToDouble(System.Configuration.ConfigurationManager.AppSettings["interval1"]);
        m_sentTransactionTimer.Interval = interval1;
        m_sentTransactionTimer.Elapsed += Foo1;
        m_sentTransactionTimer.Start();

        double interval2 = Convert.ToDouble(System.Configuration.ConfigurationManager.AppSettings["interval2"]);
        m_checkStatusTimer.Interval = interval2 ;
        m_checkStatusTimer.Elapsed += Foo2;
        m_checkStatusTimer.Start();

        double interval3= Convert.ToDouble(System.Configuration.ConfigurationManager.AppSettings["interval3"]);
        m_adaptorsTimer.Interval = interval3;
        m_adaptorsTimer.Elapsed += Foo3;
        m_adaptorsTimer.Start();

.... and some more initialization code here


        Logger.Instance.Write("***************  Service is Up  ****************", "INFO");
    }
你们知道初始化大型类的更好方法吗?使测试更容易 大体上你对这件事的看法如何

如果这是服务的“主”类,您可能不想对其进行单元测试。或者,如果它具有您希望进行单元测试的功能,您可能希望将该功能移动到单独的类中,这些类将获得所需的配置参数(以及那些)作为构造函数参数。因此,它们很容易进行单元测试

或者,如果您真的想测试这个类,您可以将
System.Configuration.ConfigurationManager
隐藏在一个可模拟的接口后面,这样您就可以轻松地传递单元测试所需的任何参数。但一般来说,你的应用程序中几乎总是会有一些高级类,它们只是初始化全部内容,从命令行/config文件/registry/DB/等等加载配置参数,然后将这些传递给其他做实际工作的类。在一个设计良好的应用程序中,这样的类只有一个职责,它通过集成/系统测试而不是单元测试进行验证

在较小范围内,上述代码在这些段中包含重复项:

    double interval1= Convert.ToDouble(System.Configuration.ConfigurationManager.AppSettings["interval1"]);
    m_sentTransactionTimer.Interval = interval1;
    m_sentTransactionTimer.Elapsed += Foo1;
    m_sentTransactionTimer.Start();

这些可以很容易地提取到一个带有参数的方法中。

只要粗略地看一下您的代码,我就觉得应该对其进行重新分解,这样您就可以避免所有重复的代码

我发现,减少重复的最好方法是将重复的代码抽象成带参数的小函数,或者使用字典和列表理解创建初始设置,然后解析运行方法的列表

这将创建非常整洁、易于阅读和维护的代码

可以重构成类似

var addressList = new List<string>() { "1Address", "2Address", "3Address" };
var composedAddress = new List<Address>();    
addressList.ForEach(address => composedAddress.Add(new EndpointAddress(
    System.Configuration.ConfigurationManager.AppSettings[address]))
);
var addressList=newlist(){“1地址”、“2地址”、“3地址”};
var composedAddress=新列表();
addressList.ForEach(地址=>ComposeAddress.Add(新端点地址(
System.Configuration.ConfigurationManager.AppSettings[地址])
);
此外,你也可以在你的间歇时间做同样的事情

var intervalList = new List<Tuple<string, timer, delegate>>() { 
  new Tuple<string, timer, delegate> { "Interval1", m_sentTransactionTimer, Foo1 },  
  new Tuple<string, timer, delegate>  { "Interval2" m_checkStatusTimer, Foo2 }, 
  new Tuple<string, timer, delegate> { "Interval3", m_adaptorsTimer , Foo3 }  
}

intervalList.ForEach(tuple => {
  var interval = Convert.ToDouble(System.Configuration.ConfigurationManager.AppSettings[tuple.Item1])
  tuple.Item2.Interval = interval;
  tuple.Item2.Elapsed += tuple.Item3;
  tuple.Item2.Start();
});    
var intervalList=new List(){
新元组{“Interval1”,m_sentTransactionTimer,Foo1},
新元组{“Interval2”mu checkStatusTimer,Foo2},
新元组{“Interval3”,m_AdapterTimer,Foo3}
}
intervalList.ForEach(元组=>{
var interval=Convert.ToDouble(System.Configuration.ConfigurationManager.AppSettings[tuple.Item1])
tuple.Item2.Interval=间隔;
tuple.Item2.appeased+=tuple.Item3;
tuple.Item2.Start();
});    
此外,您可能希望确保您的BServiceClass不会承担比它应该承担的更多的责任。一个类应该只有一个职责。遵循单一的责任原则,你应该考虑抽象出任何违反单一责任的代码。

BService构造函数应该是描述正在发生的事情的高阶函数

BService() {
    Initialize(addressList, intervalList, someotherList);
    Logger.Instance.Write("***************  Service is Up  ****************", "INFO");

}

Initialize(List<string>, List<Tuple<string, timer, delegate>>, ...){
  ...
}
BService(){
初始化(地址列表、间隔列表、其他列表);
Logger.Instance.Write(“****************服务已启动,****************”,“信息”);
}
初始化(列表,列表,…){
...
}

谢谢。。关于你的第二条评论,我只是复制粘贴一些代码。关于你的第一条评论,最好在c'tor中全部初始化吗?@guyl,如果可以的话,通常最好在那里初始化(当然,如果它开始变得太长,你应该提取一些方法,使其简短易懂)。但这并不总是可能的,例如,如果两个类都有循环依赖关系,使得它们都需要另一个的现有对象来进行自身的初始化。