工作原理
它通过在WEB服务中揭示两个方法来工作——ExecuteMethod和ExecuteArrayMethod。这两个方法接受同样的参数,其内部工作原理也基本相同。其不同在于一个返回一ArrayList对象,一个返回一个对象。
这些方法要求你告诉它们你希望使用业务层中的哪个类(typeName参数),执行那个类中的哪个方法(方法参数——记住这里我们使用的是静态方法),送给那个方法什么值作参数(引数参数)。一旦WEB服务被调用,它访问业务类,用Type.Invoke方法执行带指定参数的方法,然后返回与商业类方法返回的相同值。
所以,基本上我们没有通过WEB服务直接在业务逻辑层上执行任何操作。你指导WEB服务执行哪个方法,它就动态执行这个方法。
代码
这种动态WEB服务的代码如列表A所示。
列表A
C# Code:
///<summary>
/// Summary description for BusinessPipe.
///</summary>
[WebService(Namespace="http://tempuri/")]
[XmlInclude(typeof(CustomerData)),XmlInclude(typeof(OrderData))]
publicclass BusinessPipe : System.Web.Services.WebService
{
//This should be set to the name of your business logic assembly.
privateconststring BUSINESS_ASSEMBLY = "My.Business.Assembly";
#region Component Designer generated code
//Required by the Web Services Designer
private IContainer components = null;
///<summary>
/// Clean up any resources being used.
///</summary>
protectedoverridevoid Dispose( bool disposing )
{
if(disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
private Type AccessType(string typeName)
{
Type type = null;
Assembly assembly = System.Reflection.Assembly.Load(BUSINESS_ASSEMBLY);
if(assembly == null)
thrownew Exception("Could not find assembly in BusinessPipe!");
type = assembly.GetType(BUSINESS_ASSEMBLY + "." + typeName);
if(type == null)
thrownew Exception("Could not find type!");
return type;
}
///<summary>
/// Executes a method on the Business Logic and returns whatever object that
/// method returns.
///</summary>
///<param name="typeName">The class in the Business Logic to reference.</param>
///<param name="method">The method that you want to execute in the class.</param>
///<param name="arguments">The arguments to send to the method.</param>
///<returns>The same object that the business logic method returns.</returns>
[WebMethod]
publicobject ExecuteMethod(string typeName, string method,
paramsobject[] arguments)
{
object returnObject = null;
Type type = AccessType(typeName);
try
{
returnObject = type.InvokeMember(method,
BindingFlags.Default | BindingFlags.InvokeMethod,
null, null, arguments);
}
catch
{
//Do some custom exception handling here.
throw;
}
return returnObject;
}
///<summary>
/// Executes a method on the Business Logic and returns the same ArrayList that
/// the method returns.
///</summary>
///<param name="typeName">The class in the Business Logic to reference.</param>
///<param name="method">The method that you want to execute in the class.</param>
///<param name="arguments">The arguments to send to the method.</param>
///<returns>The same object that the business logic method returns.</returns>
[WebMethod]
public ArrayList ExecuteArrayMethod(string typeName, string method,
paramsobject[] arguments)
{
ArrayList returnObject = null;
Type type = AccessType(typeName);
try
{
returnObject = type.InvokeMember(method,
BindingFlags.Default | BindingFlags.InvokeMethod,
null, null, arguments) as ArrayList;
}
catch
{
//Do some custom exception handling here.
throw;
}
return returnObject;
}
}
代码注释
注意在WEB服务顶部,我包含了两个XmlInclude语句。要求这两个语句使框架了解如何序列化OrderData和CustomerData对象。你需要为每种类型的对象(它们要么送交到WEB服务,要么由WEB服务发出)增加这些语句。而且,包含业务逻辑的配件必须从WEB服务中引用。如果不是这样,WEB服务将不能访问业务逻辑。
缺陷
这种方法存在一些缺陷:
- 你失去WEB服务的IntelliSense和被调用的方法。如果你打算由其它部分耗用WEB服务,或你的开发者并不熟悉业务逻辑代码,这确实是一种缺陷。这还意味着你在与WEB服务交互时会失去类型安全。在我看来,失去类型安全是这种技巧最大的缺点。
- 没有内置的安全机制限制可从WEB服务访问的业务逻辑方法。
虽然这些确实是问题,但我觉得可以相对容易地解决并更正它们。
- 要允许IntelliSense,你可以轻松建立仅仅处理对来自WEB服务的请求/响应的代理类。但是,由于你必须使代理类与业务类保持同步,这种方法取消了这种动态WEB服务的一个优点。
- 为保证安全,你可以使用定制属性来定义可见与不可见的业务逻辑方法。在调用Type.Invoke()之前应用反射来检查属性可以相对方便地完成这一任务。
并非万能
本文详细说明的解决方案当然不能适用于一切情形。例如,它不能用于外部WEB服务。但是,某些情况下,这种类型的解决方案可节省大量时间。当它与数据库映射功能组合使用时,我的工作团队编写的代码比应用传统技巧时减少了大约60%。
(文/Zach Smith,techrepublic.com.com)
责任编辑:张琎
查看本文的国际来源 |