c# – 如果字段是实例成员,则使用Callback Handler异常
希望有人帮助我
如果CallbackHandler.proxy是静态的,那么一切正常: using System; using System.ServiceModel; namespace ConsoleApplication5 { // Define class which implements callback interface of duplex contract public class CallbackHandler : ServiceReference1.IStockServiceCallback { public static InstanceContext site = new InstanceContext(new CallbackHandler()); public static ServiceReference1.StockServiceClient proxy = new ServiceReference1.StockServiceClient(site); // called from the service public void PriceUpdate(string ticker,double price) { } } class Program { static void Main(string[] args) { CallbackHandler cbh = new CallbackHandler(); } } } 但是,如果我将它声明为实例成员,那么我得到System.TypeInitializationException:CallBackHandler的类型初始化程序’引发了异常. —> System.ArgumentNullException.值不能为null异常 using System; using System.ServiceModel; namespace ConsoleApplication5 { // Define class which implements callback interface of duplex contract public class CallbackHandler : ServiceReference1.IStockServiceCallback { public static InstanceContext site = new InstanceContext(new CallbackHandler()); public ServiceReference1.StockServiceClient proxy = new ServiceReference1.StockServiceClient(site); // called from the service public void PriceUpdate(string ticker,double price) { } } class Program { static void Main(string[] args) { CallbackHandler cbh = new CallbackHandler(); } } } 知道为什么让CallbackHandler.proxy成为实例成员会引发异常吗? 编辑:
因此,在第二种情况下,站点应该初始化为null,而在第一种情况下应该为它分配一个非空值?! 但… 起初我认为静态站点为null(无论代理是实例还是静态成员)只是因为它是用CallbackHandler初始化的,如下所述:
然后我记得如果代理也是静态的,那么该站点不为null,所以我对正在发生的事情的理解改为:
但是后来我运行了你的测试代码,由于某种原因,即使代理不是静态的,也会分配站点(因此不为空): using System; namespace ConsoleApplication5 { public class InstanceContext { public InstanceContext(CallbackHandler ch) { Console.WriteLine("new InstanceContext(" + ch + ")"); } } public class StockServiceClient { public StockServiceClient(InstanceContext ic) { Console.WriteLine("new StockServiceClient(" + ic + ")"); } } // Define class which implements callback interface of duplex contract public class CallbackHandler { public static InstanceContext site = new InstanceContext(new CallbackHandler()); public StockServiceClient proxy = new StockServiceClient(site); public CallbackHandler() { Console.WriteLine("new CallbackHandler()"); } static CallbackHandler() { Console.WriteLine("static CallbackHandler()"); } } class Program { static void Main(string[] args) { Console.WriteLine(CallbackHandler.site == null); // returns false } } } 到底是怎么回事? 解决方法
问题出在这一行:
public static InstanceContext site = new InstanceContext(new CallbackHandler()); 这条线真的很邪恶! 必须在执行上面给出的行的新CallbackHandler()之前完成CallbackHandler的静态初始化(因为这会创建一个实例).但是这一行隐含了静态构造函数的一部分!所以我认为.NET运行时无法执行此行,并使站点未初始化(或稍后初始化).这就是代理初始化站点仍为空的原因. 顺便说一下,我不确定是否定义了静态初始化的顺序.考虑这样一个例子: class Test { static Twin tweedledum = new Twin(tweedledee); static Twin tweedledee = new Twin(tweedledum); } 编辑: 编辑:
我们所做的确实是一个循环依赖:CallbackHandler依赖于它自己.因此,您获得的行为实际上已记录在案,并且符合标准. 编辑: 编辑: 在第一种情况下,您的代码被隐式重写为 public static InstanceContext site; public static ServiceReference1.StockServiceClient proxy; static CallbackHandler() { site = new InstanceContext(new CallbackHandler()); proxy = new ServiceReference1.StockServiceClient(site); } 在第二种情况下,你得到 public static InstanceContext site; public ServiceReference1.StockServiceClient proxy; static CallbackHandler() { site = new InstanceContext(new CallbackHandler()); // (*) } public CallbackHandler() { proxy = new ServiceReference1.StockServiceClient(site); } 在第二种情况下,标记为(*)的行中的实例构造函数在静态构造函数完成之前运行(是的,它是可能的),但此时仍未分配站点. 因此,基本上在您的第二个代码变体中,您在每个实例中都有一个单独的代理,它指向静态站点,而静态站点又引用了另一个CallbackHandler的“默认”实例.这真的是你想要的吗?也许,你只需要拥有一个实例字段吗? 因此,在代码的第二个变体中会发生以下情况: >主要开始. >执行构造函数new CallbackHandler() >使用计算的参数,将调用构造函数新的InstanceContext >作为其中的一部分,构建了一个新的代理,现在具有非null的站点值 >刚刚创建的CallbackHandler被赋值给变量cbh. 在您的情况下,ServiceReference1.StockServiceClient(site)抛出因为site为null;如果它不关心空值,代码将如上所述运行. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |