我正在创建asp.net Web服务。我有一个类,当我尝试初始化该类的对象时,其静态构造函数未被调用。我无法理解这种行为。在静态构造函数中,我正在从web.config文件中读取值。
以下是代码的一部分:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
AppController extractor;
public Service()
{
try
{
extractor = new AppController();
}
catch(Exception ex)
{
// I am not getting exception at this point.
}
}
}
public class AppController
{
static string converterBatchFilePath = null;
static string personalProfileOutputFolderPath = null;
static AppController()
{
// reading some settings from web.config file
try
{
converterBatchFilePath = ConfigurationManager.AppSettings["WordToTextConverterBatFilePath"];
}
catch(Exception ex)
{ // }
}
public AppController()
{
// do some initialization
}
}
在调试Web服务时,我注意到只有实例构造函数被调用,控件永远不会转到静态构造函数。
任何人都知道为什么会这样吗?
我正在使用VS 2008 Express版和C#。
修改
实际上这个AppController是基于控制台的项目。我已将该项目添加为Web服务项目中的参考,然后使用它。如果我从命令行使用AppController,它工作正常,但它不能在Web服务项目内部工作。
答案 0 :(得分:19)
我的猜测是,在你预期它被调用之前它被调用了。如果您已经调试过您的站点但没有回收AppPool,则很可能已经运行了静态构造函数。 类似地,任何访问任何静态成员的东西也会调用静态构造函数(如果尚未调用它)。
答案 1 :(得分:13)
今天我的静态初始化程序没有被调用。事实证明,在访问类的const成员之前,静态初始化程序是而不是。
因为const值在编译时是已知的,所以这是有意义的,但它意味着the documentation表示"它在...之前被自动调用...任何静态成员被引用"在技术上是不正确的,至少与@JonSkeet's assertion结合使用"所有常量声明都是隐式静态"。
该程序演示了这个问题:
using System;
static class Program
{
public static void Main()
{
Console.WriteLine("Constant={0}", Problem.Constant);
Console.WriteLine("ReadOnly={0}", Problem.ReadOnly);
Console.WriteLine("Field={0}", Problem.Field);
Console.WriteLine("Property={0}", Problem.Property);
}
private static class Problem
{
public const int Constant = 1;
public static readonly int ReadOnly = 2;
public static int Field = 3;
private static int mProperty = 4;
public static int Property { get { return mProperty; } }
static Problem()
{
Console.WriteLine("Problem: static initializer");
}
}
}
输出结果为:
常数= 1
问题:静态初始化器
只读= 2
字段= 3
属性= 4
(针对.NET 4.5进行测试。)
答案 2 :(得分:5)
静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。在创建第一个实例或引用任何静态成员之前会自动调用它。
请注意 在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。和用户无法控制何时在程序中执行静态构造函数。
答案 3 :(得分:2)
我怀疑你的问题是由静态构造函数中引发的异常引起的,并且被创建实例的代码吞没了。
在静态字段初始化程序中,甚至可能更难以调试。
或许打破第一次机会异常有助于调试问题。
我根本不会将从配置文件中读取的代码放入静态构造函数中。我会将所有与配置相关的内容封装在一个类中,并将该类的实例传递给构造函数,可能使用的是IoC容器。
这有许多优点:
(我知道这不是一个答案,但评论的时间太长了)
答案 4 :(得分:1)
这是一个快速示例,我将它放在一起,从静态和实例构造函数中的提取器类中的配置文件中获取值。这对我有用 - 将它与你正在做的事情进行比较,看看有什么不同:
public class Service : System.Web.Services.WebService
{
AppController extractor;
[WebMethod]
public string HelloWorld()
{
extractor = new AppController();
return AppController.staticString + " :: " + extractor.instanceString;
}
}
class AppController
{
public static string staticString;
public string instanceString;
static AppController()
{
staticString = System.Configuration.ConfigurationManager.AppSettings["static"];
}
public AppController()
{
instanceString = System.Configuration.ConfigurationManager.AppSettings["instance"];
}
}
我的web.config:
<appSettings>
<add key="static" value="blah blah"/>
<add key="instance" value="ha ha"/>
</appSettings>
我的回答:
<?xml version="1.0" encoding="UTF-8"?>
<string xmlns="http://tempuri.org/">blah blah :: ha ha</string>
答案 5 :(得分:0)
当我尝试通过在引用静态字段的行上放置一个断点进行调试时,我没有在静态构造函数上获得调试控制。
我将断点保留在静态构造函数入口处,从静态字段引用的行中删除了断点。现在,调试控件开始进入静态构造函数代码。
This image shows how your editor with breakpoints would look like