如何在多个后台页面与类之间共享依赖Page类的代码
问题:ASP.NET页面与多类共享依赖Page对象代码时遇空引用错误
我需要在多个Code Behind页面和多个类之间共享依赖Page类对象与方法(如Response、Session、GridView、Panel等)的代码,将这类通用代码存入多个共享类实现复用。
按照建议实现示例代码后,发现从Class1调用Class2_Procedure时会触发“Object reference not set to an instance of an object”错误;但直接从页面调用Class1_Procedure和Class2_Procedure却能正常运行。
示例代码
页面代码
Partial Class _default Inherits System.Web.UI.Page Dim MyClass1 As New Class1(Me) Dim MyClass2 As New Class2(Me) Private Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load Response.Write("Default Page > Page_Load<br/>") MyClass1.Class1_Procedure() MyClass2.Class2_Procedure() MyClass1.Class1_Procedure_Calling_Class2_Procedure() End Sub End Class
Class1代码
Public Class Class1 Dim MyPage As Page Sub New(MePage As Page) MyPage = MePage End Sub Dim MyClass2 As New Class2(MyPage) Sub Class1_Procedure() MyPage.Response.Write("Class1 > Class1_Procedure<br/>") End Sub Sub Class1_Procedure_Calling_Class2_Procedure() MyPage.Response.Write("Class1 > Class1_Procedure_Calling_Class2_Procedure<br/>") MyClass2.Class2_Procedure() End Sub End Class
Class2代码
Public Class Class2 Dim MyPage As Page Sub New(MePage As Page) MyPage = MePage End Sub Sub Class2_Procedure() MyPage.Response.Write("Class2 > Class2_Procedure<br/>") End Sub End Class
问题原因与解决方案
错误根源
在Class1中,Dim MyClass2 As New Class2(MyPage)属于类级字段的初始化代码,它的执行顺序早于类的构造函数Sub New。也就是说,当创建MyClass2实例时,MyPage还没被构造函数赋值,此时MyPage是Null,传递给Class2的构造函数后,Class2里的MyPage自然也是Null,调用Class2_Procedure时就会触发空引用错误。
修正方案
把MyClass2的初始化逻辑移到构造函数内部,确保MyPage已经被赋值后再创建Class2实例:
Public Class Class1 Dim MyPage As Page Dim MyClass2 As Class2 ' 先声明字段,暂不初始化 Sub New(MePage As Page) MyPage = MePage MyClass2 = New Class2(MyPage) ' 构造函数内完成初始化,此时MyPage已有有效值 End Sub Sub Class1_Procedure() MyPage.Response.Write("Class1 > Class1_Procedure<br/>") End Sub Sub Class1_Procedure_Calling_Class2_Procedure() MyPage.Response.Write("Class1 > Class1_Procedure_Calling_Class2_Procedure<br/>") MyClass2.Class2_Procedure() End Sub End Class
可选优化:延迟初始化
如果不想在构造函数里提前初始化MyClass2,也可以用延迟初始化的方式,在第一次使用时再创建实例:
Public Class Class1 Dim MyPage As Page Private _myClass2 As Class2 ' 通过属性实现延迟初始化 Private ReadOnly Property MyClass2 As Class2 Get If _myClass2 Is Nothing Then _myClass2 = New Class2(MyPage) End If Return _myClass2 End Get End Property Sub New(MePage As Page) MyPage = MePage End Sub Sub Class1_Procedure() MyPage.Response.Write("Class1 > Class1_Procedure<br/>") End Sub Sub Class1_Procedure_Calling_Class2_Procedure() MyPage.Response.Write("Class1 > Class1_Procedure_Calling_Class2_Procedure<br/>") MyClass2.Class2_Procedure() ' 第一次调用时才初始化 End Sub End Class
额外建议
- 降低耦合:可以定义一个
IPageContext接口,只暴露业务需要用到的Page成员(如Response、Session),然后让Page实现这个接口,再传递接口实例给共享类,避免直接依赖整个Page对象。 - 依赖注入:如果项目规模较大,可使用依赖注入框架(如Autofac、Unity)来管理Page相关对象的注入,减少手动传递的代码。
内容的提问来源于stack exchange,提问作者ptownbro
相关产品推荐
相关产品推荐

