您的位置:首页 > 编程语言 > ASP

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

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




Xiaozhuang.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赋值给实现接口的全局静态属性。




Code


namespace Xiaozhuang.Web






{


public class Global : System.Web.HttpApplication, IContainerAccessor






{






Members#region Members




private static IUnityContainer _container;




#endregion






Properties#region Properties






/**//// <summary>


/// The Unity container for the current application


/// </summary>


public static IUnityContainer Container






{


get






{


return _container;


}


set






{


_container = value;


}


}




#endregion






IContainerAccessor Members#region IContainerAccessor Members






/**//// <summary>


/// Returns the Unity container of the application


/// </summary>


IUnityContainer IContainerAccessor.Container






{


get






{


return Container;


}


}




#endregion






Application Events#region Application Events




protected void Application_Start(object sender, EventArgs e)






{


BuildContainer();


}




protected void Session_Start(object sender, EventArgs e)






{




}




protected void Application_BeginRequest(object sender, EventArgs e)






{




}




protected void Application_AuthenticateRequest(object sender, EventArgs e)






{




}




protected void Application_Error(object sender, EventArgs e)






{




}




protected void Session_End(object sender, EventArgs e)






{




}




protected void Application_End(object sender, EventArgs e)






{


CleanUp();


}


#endregion






Methods#region Methods




private static void BuildContainer()






{


UnityContainerConfig config = new UnityContainerConfig();


Container = config.GetIUnityContainer();


}


private static void CleanUp()






{




if (Container != null)






{




Container.Dispose();




}




}




#endregion


}


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




BasePage
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", "<script>alert('当前Http上下文为空,请与系统管理员联系!');</script>");
}
var accessor = context.ApplicationInstance as IContainerAccessor;
if (accessor == null)
{
ClientScript.RegisterClientScriptBlock(this.GetType(), "context", "<script>alert('当前应用程序实例为空,请与系统管理员联系!');</script>");
}
var container = accessor.Container;
if (container == null)
{
ClientScript.RegisterClientScriptBlock(this.GetType(), "context", "<script>alert('未找到依赖注入容器,请与系统管理员联系!');</script>");
}
container.BuildUp(this as T);
}
}
}
我们不止在页面中要调用接口,也要在UserControl中调用,那么我们就参照上面的页面基类建立一个UserControl的泛型基类。




BaseUserControl
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", "<script>alert('当前Http上下文为空,请与系统管理员联系!');</script>");
}
var accessor = context.ApplicationInstance as IContainerAccessor;
if (accessor == null)
{
this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "context", "<script>alert('当前应用程序实例为空,请与系统管理员联系!');</script>");
}
var container = accessor.Container;
if (container == null)
{
this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "context", "<script>alert('未找到依赖注入容器,请与系统管理员联系!');</script>");
}
container.BuildUp(this as T);
}
}
}
接下来我们建立一个UserControl文件,在里面调用查询雇员的服务接口,并绑定到ListView控件上,具体代码如下:




Code
namespace Xiaozhuang.Web
{
public partial class EmployeeList : BaseUserControl<EmployeeList>
{

#region Properties

[Dependency]
public IQueryEmployeeService instance { set; get; }

public QueryEntry queryentry { set; get; }

#endregion
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
try
{
ListView1.DataSource = instance.QueryEmployee(queryentry);
ListView1.DataBind();
}
catch
{

Response.Write("系统运行错误,请与管理员联系!");
}
}
}
}
}
这个EmployeeList继承自BaseUserControl<T>.UserControl基类,这样这个用户控件就可以实现注入了,我们只需要在属性上增加Dependency标记就可以用属性注入的方式来调用接口方法,当然你也可以通过方法注入的方式来实现。
接下来我们要用Asp.net Ajax调用这个UserControl来生成HTML,给页面上使用,我们先建立两个类ControlPage和ViewManager




Code
namespace Xiaozhuang.Web
{
public class ControlPage : Page
{
public override void VerifyRenderingInServerForm(Control control)
{
//base.VerifyRenderingInServerForm(control);
}
}
}
namespace Xiaozhuang.Web
{
/// <summary>
/// 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.
/// </summary>
/// <typeparam name="T">The type of the control you are rendering</typeparam>
public class ViewManager<T> where T : Control
{

#region Properties

private T _control = default(T);

/// <summary>
/// Gives you access to the control you are rendering allows
/// you to set custom properties etc.
/// </summary>
public T Control
{
get
{
return _control;
}
}

// Used as a placeholder page to render the control on.
private ControlPage _holder = null;

#endregion

#region Constructor

/// <summary>
/// Default constructor for this view manager, pass in the path for the control
/// that this view manager is render.
/// </summary>
/// <param name="inPath"></param>
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

/// <summary>
/// Renders the current control.
/// </summary>
/// <returns></returns>
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标记的方法,如下




Code
[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中。如下




Code
<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的方法我用了很久了,本来这次是写架构设计的,给扯到这上面来了,也许这也算是架构设计的一部分吧。
运行效果如下:



Tag标签: IOC,依赖注入,Unity,架构,UserControl生成Html,Asp.Net Ajax,UserControl
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: