首页 > Asp.Net开发架构设计(二)

Asp.Net开发架构设计(二)

上回说到,我们配置了一下UnityConfig层,在这个层中定义了一个IContainerAccessor的接口和一个返回IUnityContainer类型的方法,这个方法的主要作用就是把Service层中的接口类和Business层中的接口实现类装配到UnityContainer中并返回,也就是指定那个接口实现类去实现某个接口类(晕,好像有点绕口啊)。

 

ContractedBlock.gifExpandedBlockStart.gifXiaozhuang.UnityConfig

namespace Xiaozhuang.UnityConfig

{

    

        
public interface IContainerAccessor

        {

            IUnityContainer Container { 
get; }

        }



        
public class UnityContainerConfig

        {

            
public IUnityContainer GetIUnityContainer()

            {

                IUnityContainer container 
= new UnityContainer();

                container.RegisterType
<IQueryEmployeeService, QueryEmployeeBusiness>();

                
return container;

            }



        }

    

}

 

好了,现在终于轮到Web层了,要实现在Asp.Net页面中直接调用能够服务接口而不用从Unity容器中再去取出来,就要把Unity容器中的接口注入到页面中去,分两步走:第一步,在Global.Asax.cs中实现UnityConfig层中的IContainerAccessor接口,并把UnityConfig层返回的IUnityContainer赋值给实现接口的全局静态属性。

 

ContractedBlock.gifExpandedBlockStart.gifCode

namespace Xiaozhuang.Web

ExpandedBlockStart.gifContractedBlock.gif
{

    
public class Global : System.Web.HttpApplication, IContainerAccessor

ExpandedSubBlockStart.gifContractedSubBlock.gif    
{



ContractedSubBlock.gifExpandedSubBlockStart.gif        
Members#region Members



        
private static IUnityContainer _container;



        
#endregion




ContractedSubBlock.gifExpandedSubBlockStart.gif        
Properties#region Properties



ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// 

        
/// The Unity container for the current application

        
/// 


        public static IUnityContainer Container

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{

            
get

ExpandedSubBlockStart.gifContractedSubBlock.gif            
{

                
return _container;

            }


            
set

ExpandedSubBlockStart.gifContractedSubBlock.gif            
{

                _container 
= value;

            }


        }




        
#endregion




ContractedSubBlock.gifExpandedSubBlockStart.gif        
IContainerAccessor Members#region IContainerAccessor Members



ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// 

        
/// Returns the Unity container of the application 

        
/// 


        IUnityContainer IContainerAccessor.Container

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{

            
get

ExpandedSubBlockStart.gifContractedSubBlock.gif            
{

                
return Container;

            }


        }




        
#endregion




ContractedSubBlock.gifExpandedSubBlockStart.gif        
Application Events#region Application Events



        
protected void Application_Start(object sender, EventArgs e)

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{

            BuildContainer();

        }




        
protected void Session_Start(object sender, EventArgs e)

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{



        }




        
protected void Application_BeginRequest(object sender, EventArgs e)

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{



        }




        
protected void Application_AuthenticateRequest(object sender, EventArgs e)

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{



        }




        
protected void Application_Error(object sender, EventArgs e)

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{



        }




        
protected void Session_End(object sender, EventArgs e)

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{



        }




        
protected void Application_End(object sender, EventArgs e)

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{

            CleanUp();

        }


        
#endregion




ContractedSubBlock.gifExpandedSubBlockStart.gif        
Methods#region Methods



        
private static void BuildContainer()

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{

            UnityContainerConfig config 
= new UnityContainerConfig();

            Container 
= config.GetIUnityContainer();

        }


        
private static void CleanUp()

ExpandedSubBlockStart.gifContractedSubBlock.gif        
{



            
if (Container != null)

ExpandedSubBlockStart.gifContractedSubBlock.gif            
{



                Container.Dispose();



            }




        }




        
#endregion


    }


}

接下来要把UnityContainer中的接口注入到页面中去。建立一个BasePage的泛型类,先获取到从Gloab.Asax传过来的应用程序实例,转化为UnityContainer,利用BuildUp方法注入到页面中去。

 

ContractedBlock.gifExpandedBlockStart.gifBasePage

namespace Foresee.Web

{

    
public abstract class BasePage<T> : Page where T : class

    {

        
protected override void OnPreInit(EventArgs e)

        {

            InjectDependencies();

            
base.OnPreInit(e);

        }

        
protected virtual void InjectDependencies()

        {

            var context 
= HttpContext.Current;

            
if (context == null)

            {

                ClientScript.RegisterClientScriptBlock(
this.GetType(), "context""");

            }

            var accessor 
= context.ApplicationInstance as IContainerAccessor;

            
if (accessor == null)

            {

                ClientScript.RegisterClientScriptBlock(
this.GetType(), "context""");

            }

            var container 
= accessor.Container;

            
if (container == null)

            {

                ClientScript.RegisterClientScriptBlock(
this.GetType(), "context""");

            }

            container.BuildUp(
this as T);

        }

    }

}

我们不止在页面中要调用接口,也要在UserControl中调用,那么我们就参照上面的页面基类建立一个UserControl的泛型基类。

 

ContractedBlock.gifExpandedBlockStart.gifBaseUserControl

namespace Foresee.Web

{

    
public abstract class BaseUserControl<T> : UserControl where T : class

    {

        
protected override void OnInit(EventArgs e)

        {

            InjectDependencies();

            
base.OnInit(e);

        }

        
protected virtual void InjectDependencies()

        {

            var context 
= HttpContext.Current;

            
if (context == null)

            {

                
this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "context""");

            }

            var accessor 
= context.ApplicationInstance as IContainerAccessor;

            
if (accessor == null)

            {

                
this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "context""");

            }

            var container 
= accessor.Container;

            
if (container == null)

            {

                
this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "context""");

            }

            container.BuildUp(
this as T);

        }

    }

}

接下来我们建立一个UserControl文件,在里面调用查询雇员的服务接口,并绑定到ListView控件上,具体代码如下:

 

ContractedBlock.gifExpandedBlockStart.gifCode

namespace Xiaozhuang.Web

{

    
public partial class EmployeeList : BaseUserControl<EmployeeList>

    {

        

        
#region Properties



        [Dependency]

        
public IQueryEmployeeService instance { setget; }



        
public QueryEntry queryentry { setget; }



        
#endregion

        
protected void Page_Load(object sender, EventArgs e)

        {

            
if (!IsPostBack)

            {

                
try

                {

                    ListView1.DataSource 
= instance.QueryEmployee(queryentry);

                    ListView1.DataBind();

                }

                
catch 

                {

                   

                   Response.Write(
"系统运行错误,请与管理员联系!");

                }

            }

        }

    }

}

这个EmployeeList继承自BaseUserControl.UserControl基类,这样这个用户控件就可以实现注入了,我们只需要在属性上增加Dependency标记就可以用属性注入的方式来调用接口方法,当然你也可以通过方法注入的方式来实现。

接下来我们要用Asp.net Ajax调用这个UserControl来生成HTML,给页面上使用,我们先建立两个类ControlPage和ViewManager

 

ContractedBlock.gifExpandedBlockStart.gifCode

namespace Xiaozhuang.Web

{

    
public class ControlPage : Page

    {

        
public override void VerifyRenderingInServerForm(Control control)

        {

            
//base.VerifyRenderingInServerForm(control);

        }

    }

}

namespace Xiaozhuang.Web

{

    
/// 

    
/// A generic user control rendering helper, basically you initialise the view manager and 

    
/// call render to render that control, but the benifit of this version is you can access the control

    
/// the view manager is rendering and can set custom properties etc.

    
/// 


    
/// The type of the control you are rendering

    public class ViewManager<T> where T : Control

    {



        
#region Properties



        
private T _control = default(T);



        
/// 

        
/// Gives you access to the control you are rendering allows

        
/// you to set custom properties etc.

        
/// 


        public T Control

        {

            
get

            {

                
return _control;

            }

        }



        
// Used as a placeholder page to render the control on.

        private ControlPage _holder = null;



        
#endregion



        
#region Constructor



        
/// 

        
/// Default constructor for this view manager, pass in the path for the control

        
/// that this view manager is render.

        
/// 


        
/// 

        public ViewManager(string path)

        {

            
//Init the holder page

            _holder = new ControlPage();



            
// Create an instance of our control

            _control = (T)_holder.LoadControl(path);



            
// Add it to our holder page.

            _holder.Controls.Add(_control);

        }



        
#endregion



        
#region Rendering



        
/// 

        
/// Renders the current control.

        
/// 


        
/// 

        public string Render()

        {

            StringWriter sw 
= new StringWriter();



            
// Execute the page capturing the output in the stringwriter.

            HttpContext.Current.Server.Execute(_holder, sw, false);



            
// Return the output.

            return sw.ToString();

        }



        
#endregion



    }

}

ControlPage类是一个简单的继承Page的类,里面重载VerifyRenderingInServerForm方法的作用是防止在UserControl生成HTML的时候如果UserControl中有服务器控件而出现的“服务器控件必须放在Form ruanat=‘server’”的错误!ViewManager类的作用是把在服务器端UserControl装在ControlPage页面中用Excute方法执行一遍并用Render方法获取到执行后输出的HTML字符串。

接下来我们到页面中去,在页面类中建立一个输出HTML的静态带WebService标记的方法,如下

 

ContractedBlock.gifExpandedBlockStart.gifCode

[WebMethod()]

        
public static string GetDataPage(int page, string departmentID, string EmpName, string EmpAge)

        {

            
// Create an instance of our viewmanager.

            ViewManager<EmployeeList> man = new ViewManager<EmployeeList>("~/EmployeeList.ascx");

            QueryEntry queryentry 
= new QueryEntry();

            queryentry.DepartmentID 
= departmentID;

            queryentry.EmployeeName 
= EmpName;

            queryentry.EmployeeAge 
= EmpAge;



            man.Control.queryentry 
= queryentry;

            
return man.Render();

        }

这个方法的作用是吧查询的参数传递给EmployeeList用户控件,通过ViewManager执行并输出HTML字符串,在Aspx页面中用Asp.Net Ajax代码来调用这个方法,并把返回的html填充到相应的Div中。如下

 

ContractedBlock.gifExpandedBlockStart.gifCode

<script type="text/javascript">

    
var currentPage = 0;    

        
function LoadPage(page) {

         
var departmentID = document.getElementById("txtDept").value;

          
var empName = document.getElementById("txtName").value;

           
var empAge = document.getElementById("txtAge").value;

            PageMethods.GetDataPage(page,departmentID,empName,empAge, 
function(result) {

                
// We loaded our data populate our div.                

                document.getElementById("DivContent").innerHTML = result;

            },

            
function(error) {

                alert(error.get_message());

            });

        }

          Sys.Application.add_load(LoadPage);

    
</script>

 

至此写完,其实这个生成html的方法我用了很久了,本来这次是写架构设计的,给扯到这上面来了,也许这也算是架构设计的一部分吧。

运行效果如下:

转载于:https://www.cnblogs.com/xiaozhuang/archive/2008/08/21/1272963.html

更多相关:

  • 上篇笔记中梳理了一把 resolver 和 balancer,这里顺着前面的流程走一遍入口的 ClientConn 对象。ClientConn// ClientConn represents a virtual connection to a conceptual endpoint, to // perform RPCs. // //...

  • 我的实验是基于PSPNet模型实现二维图像的语义分割,下面的代码直接从得到的h5文件开始往下做。。。 也不知道是自己的检索能力出现了问题还是咋回事,搜遍全网都没有可以直接拿来用的语义分割代码,东拼西凑,算是搞成功了。 实验平台:Windows、VS2015、Tensorflow1.8 api、Python3.6 具体的流程为:...

  • Path Tracing 懒得翻译了,相信搞图形学的人都能看得懂,2333 Path Tracing is a rendering algorithm similar to ray tracing in which rays are cast from a virtual camera and traced through a s...

  • configure_file( [COPYONLY] [ESCAPE_QUOTES] [@ONLY][NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ]) 我遇到的是 configure_file(config/config.in ${CMAKE_SOURCE_DIR}/...

  •     直接复制以下代码创建一个名为settings.xml的文件,放到C:UsersAdministrator.m2下即可