通过反射(Reflection)实现对ref和out参数在 Portal-Builder 开源门户系统中的调用
2012-03-20 21:45
471 查看
最近做的Portal-Builder 开源门户系统里面用到了相当多的反射(不知道这样叫中文对不对,英文是Reflection),很多人对ref和out参数如何传递使用不太清楚,在这里我来给大家介绍一下:
其实实现我们大部分时间是采用 MethodInfo.Invoke() 来实现,所以细节就在怎么使用 Type.GetMethod()这个方法了
解密:
Type 里面有 MakeByRefType()和 MakeArrayType() 两个方法, 其中 ref和out 都可以通过MakeByRefType 来实现, 因为 ref和out 其实都可以当作是把方法外的参数当作一个 object对象传入,从而实现带值返回。 MakeArratType简单介绍就是声明传入的数据为数组,如是而已。
下面附带一下 Portal-Builder 开源门户里面的使用ActionRunner来调用XML实现类方法调用的例子:
PortalBuilderActions.xml 代码样例
后台中调用和实现反射动态调用方法的代码:
以上代码引用了工作流引擎概念 仅供Portal Builder 开源门户系统开发者讨论研究 有看不懂的地方还请见谅,有问题可以到 http://bbs.oelite.com 进行进一步讨论
其实实现我们大部分时间是采用 MethodInfo.Invoke() 来实现,所以细节就在怎么使用 Type.GetMethod()这个方法了
解密:
Type 里面有 MakeByRefType()和 MakeArrayType() 两个方法, 其中 ref和out 都可以通过MakeByRefType 来实现, 因为 ref和out 其实都可以当作是把方法外的参数当作一个 object对象传入,从而实现带值返回。 MakeArratType简单介绍就是声明传入的数据为数组,如是而已。
下面附带一下 Portal-Builder 开源门户里面的使用ActionRunner来调用XML实现类方法调用的例子:
PortalBuilderActions.xml 代码样例
<?xml version="1.0" encoding="utf-8" ?> <PortalBuilderActions> <!--每个应用下面应该都有一个PortalBuilderActions.xml 在系统启动时会全部读入系统Cache用于高速运算--> <!-- <Applicatoin> Name: 当前操作集所属应用程序的名称 AppKey: 当前操作及所属应用程序的唯一码 --> <Application Name="PBFramework" AppKey="EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F"> <!-- <ActionGroup> 应用开发者对自己应用程序内操作的归类,方便进行管理 --> <ActionGroup Name="会员操作"> <!-- <Actions> 操作集 <Action> :单个操作的定义 Name: 单个操作的名称定义, 注意:整个应用程序下,操作名称定义必须唯一 <Flows> 定义操作中的操作流:操流可以为多项内容,即该项操作涉及到多个代码方面的执行,Flow分为两种 <ManagerFlow> 直接对接Portal-Builder应用代码的操作流,通过定义 ClassName、 AssemblyName、 MethodName 用反射方法来实现方法的调用 <ActionFlow> 调用另外一个操作定义,在执行完毕另外一项操作后返回继续执行当前操作流 <Params> 操作中来自于外部的参数 Name - 参数名称定义,注意:每个操作下的Param Name必须唯一 ValueType - 参数的类型定义 DefaultValue - 参数的默认值(如果在信息传输中没有设定该值的话,就自动采用默认值;如果默认值未设,则默认为Null) ParamModifier - 参数的Modifier; 默认未设, 可以为 "out" "ref" 或空 <Result> 定义每个ManagerFlow的返回值;为设定则默认为 void <EndResults> 用于设定整个操作所需要返回的结果,其内部的ReferenceName 即设定整个操作流中所应用和生成的数据中需要返回的变量; 代码中,ActionRunner.cs 将会以object[] 的形式返回所有需要返回的内容 ReturnTrueOrFalseOnly : 如果此属性为True, 则EndResults内所有子项均被忽略,ActionRunner.cs 的object[] 返回值仅包含一个True/False 结果,代表 此操作的最终结果(其中任何一操作流失败均为失败) --> <Actions> <Action Name="CreateNewUser"> <Flows> <ManagerFlow Name="InitCreateUser" ClassName="WebCider.PortalBuilder.Framework.Base.PortalUserManager" AssemblyName="WebCider.PortalBuilder.Framework" MethodName="CreateNewUser" > <Params> <Param Name="NewUserObject" ValueType="WebCider.PortalBuilder.Common.Base.PortalUser" DefaultValue="Null" ParamModifier="out" /> </Params> <Result Name="CreateUserResult" ClassName="WebCider.PortalBuilder.Docs.DocCollection" AssemblyName="WebCider.PortalBuilder" /> </ManagerFlow> <ActionFlow Name="SendEmail" AppKey="" /> </Flows> <EndResults ReturnTrueOrFalseOnly="false"> <ReferenceName Name="NewUserObject" /> <ReferenceName Name="CreateUserResult" /> </EndResults> </Action> </Actions> </ActionGroup> </Application> </PortalBuilderActions>
后台中调用和实现反射动态调用方法的代码:
public class ActionRunner { public static object[] Run(string codeIdentifier, object[] paramList, Guid applicationKey = default(Guid)) { //获取Action string actionXmlFilePath = System.AppDomain.CurrentDomain.BaseDirectory + "/" + Common.Global.GlobalConfig.ConfigurationFiles.PortalBuilderActionXML; if (applicationKey != default(Guid)) actionXmlFilePath = AppManager.GetIntallationPath(applicationKey); Common.Configurations.PBActions.Action runnerAction = ActionXMLParser.GetAction(codeIdentifier, actionXmlFilePath); //创建Action所有参数值列表 Dictionary<string, object> fullParamList = new Dictionary<string, object>(); if (runnerAction != null && runnerAction.Flows != null && runnerAction.Flows.Count > 0) { foreach (Flow flow in runnerAction.Flows) { ActionFlow(paramList, fullParamList, flow); } if (runnerAction.ReturnTrueOrFalseOnly) { return new object[] { true }; } else { if (runnerAction.EndResults != null && runnerAction.EndResults.Count > 0) { List<object> returningValues = new List<object>(); foreach (EndResult endResult in runnerAction.EndResults) { var objValue = (from item in fullParamList where item.Key.ToLower() == endResult.Name.ToLower() select item.Value).FirstOrDefault(); if (objValue != null) { endResult.Value = objValue; returningValues.Add(objValue); } } return returningValues.ToArray(); } else return null; } } else { if (runnerAction.ReturnTrueOrFalseOnly) return new object[] { false }; else return null; }; } private static void ActionFlow(object[] paramList, Dictionary<string, object> fullParamList, Flow flow) { if (flow is ManagerFlow) { ManagerFlow mFlow = (ManagerFlow)flow; try { List<Type> paramTypes = new List<Type>(); if (mFlow.Params != null && mFlow.Params.Count > 0) { if (mFlow.Params.Count != paramList.Length) throw new WebCiderException("实际传入的参数数量与XML中定义的参数数量不符!"); foreach (Param param in mFlow.Params) { Type type; if (!string.IsNullOrEmpty(param.ParamModifier)) { type = Type.GetType(param.ValueType, true, true).MakeByRefType(); } else type = Type.GetType(param.ValueType, true, true); paramTypes.Add(type); fullParamList.Add(param.Name, paramList[paramTypes.IndexOf(type)]); } } MethodInfo methodInfo = Type.GetType(mFlow.ClassName + "," + mFlow.AssemblyName, true, true).GetMethod(mFlow.MethodName, BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, paramTypes.ToArray(), null); if (methodInfo == null) throw new WebCiderException("获取XML定义类或类方法失败!"); object vResult = methodInfo.Invoke(null, BindingFlags.InvokeMethod, null, paramList, null); if (vResult != null) { fullParamList.Add(mFlow.Result.Name, vResult); } } catch (Exception ex) { WebCiderHelper.Logger.Error("严重系统错误:解析操作集XML时失败([" + mFlow.ClassName + "," + mFlow.AssemblyName + "->" + mFlow.MethodName + "):" + ex.Message, ex); throw new WebCiderException("严重系统错误:解析操作集XML时失败([" + mFlow.ClassName + "," + mFlow.AssemblyName + "->" + mFlow.MethodName + "):" + ex.Message, ex); } } else if (flow is ActionFlow) { ActionFlow aFlow = (ActionFlow)flow; Common.Configurations.PBActions.Action flowAction = ActionXMLParser.GetAction(aFlow.Name, AppManager.GetIntallationPath(aFlow.ApplicationKey)); if (flowAction != null) { ActionFlow(paramList, fullParamList, aFlow); } else { WebCiderHelper.Logger.Error("严重系统错误:解析操作集XML时失败 - [" + aFlow.ApplicationKey + "] 的应用程序不存在或有错无法使用."); throw new WebCiderException("严重系统错误:解析操作集XML时失败 - [" + aFlow.ApplicationKey + "] 的应用程序不存在或有错无法使用."); } } } }
以上代码引用了工作流引擎概念 仅供Portal Builder 开源门户系统开发者讨论研究 有看不懂的地方还请见谅,有问题可以到 http://bbs.oelite.com 进行进一步讨论
相关文章推荐
- 如何通过反射调用带有ref或者out的参数的方法[迁移]
- C#如何通过反射调用带有ref或者out的参数的方法
- .NET/C#利用反射调用含ref或out参数的方法示例代码
- 利用反射调用方法时,处理ref,out参数需要注意的问题
- 利用反射调用方法时,处理ref,out参数需要注意的问题(转)
- c#方法中调用参数的值传递方式和引用传递方式,以及ref与out的区别
- (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
- 通过反射调用泛型参数方法
- 通过反射机制获得系统字体Size【ActivityManagerNative无法调用问题】
- 通过Android的反射机制实现系统属性的设置和获取
- 通过 open falcon 的 agent 的http 接口实现远程系统命令调用
- java通过反射调用不同参数的方法
- c#方法中调用参数的值传递方式和引用传递方式,以及ref与out的区别
- 返回多个不同类型参数的值(out)可变参数一维数组( params )把值从方法中带出(ref) 方法递归(方法自己调用自己与循坏类似注意return每次只能跳出一个方法))
- java通过反射调用不同参数的方法
- Android编程,通过ContentResolver调用系统URI实现的通讯录示例
- C#.NET dll封装(包含UI和实现函数),通过反射调用dll实现控件的快速加载(PrimPointListCreator.cs)
- Parallax Cubemap for Planar Reflection - Remember Me反射系统学习笔记及实现
- Python for .net脚本调用dotnet框架(ref和out参数问题)
- java通过反射调用实现类