现在的位置: 首页 > 综合 > 正文

读取 XML、反射、调用对象方法

2012年12月26日 ⁄ 综合 ⁄ 共 3044字 ⁄ 字号 评论关闭

以前没干过类似的,做反射也只限于复制属性,到处问别人但没有完全符合我要求我想法的。看看我的问题先:

不知道从什么时候开始,在业务层,做设计时候,我的业务对象和他们的方法,是分开写在不同的类和接口。这样设计好像有个名字的,那是题外话。但是,当一个业务对象与另一个业务对象,有交互时候,这些交互的方法应该写在哪里,对应的验证方法又放哪里?举个例,销售订单,销售发票,两个业务对象肯定有交互,操作时,销售发票可以是从销售订单生成,也可以创建了销售发票然后用订单的信息填满。我的做法是,再加一层,做业务逻辑,来操作这些业务对象和调用他们的方法。

另一个更简单的例子,如下图:

decouple

导入档案写入记录(第三方),做配对后映射到本域业务对象,写入,最后返回写入结果。其他业务流程也会调用到相同业务的方法,只是目的、顺序等有可能不一样。

这样我也 ok 的了,不过,如果这些操作顺序有改变,就要改“Process" 那一层了,改代码和重新编译。这些情况特别在一些商业逻辑上,经常发生,变动频繁。以前写的财务核算模块,核算规则不停的随着组织架构和成本分摊方式变化而需要改动,就是一个实例。

我希望,用 XML 定义业务流程的行为,通过改 XML(甚至是弄个界面让用户自己改),要能做到这些改动。这就是我想做的事。

最初第一想到的就是用 jBPM ( .Net 版),或者 Workflow Foundation,但感觉大材小用,有朋友介绍 Drools,分别不大。然后我上 stackoverflow 问,有位大哥说来说去都是叫我 IoC,然后我想了一下,容器还不是一样用反射,那我自己写也可以呀。

反射上面说了我不是很熟悉,弄了个简单的试验,果然能做到,如下:

<?xml version="1.0" encoding="utf-8" ?>
<rules>
   
<rule name="rule1">
       
<type name="test">
           
<Method name="method1">
               
<param></param>
           
</Method>
           
<Method name="method2">
           
</Method>
       
</type>
   
</rule>

</rules>

就用这个试,对象名字是 test,里面有两个方法,这版本在 XML 没有写明调用顺序,不过加上也很简单(本来想试一下参数传入,后来觉得能 invoke 、类型正确的话,这不可能做不到的)。下面就是代码,本来对象名称是应该取自 XML 的,我试而已,你有兴趣就自己改吧:

using System;
using System.Xml;
using System.Reflection;

namespace DynamicInvokeTest
{
   
class Program
    {
       
static void Main(string[] args)
        {
            XmlDocument doc
= new XmlDocument();
            doc.Load(
"Rule1.xml");
            XmlNodeList nodelist
= doc.GetElementsByTagName("type");
           
foreach (XmlNode x in nodelist)
            {
               
if (x.Attributes["name"].Value == "test")
                {
                   
foreach (XmlNode y in x.ChildNodes)
                    {
                       
if (y.Name == "Method")
                        {
                            Console.WriteLine(
"------------Invoke now--------------");

                            object[] argument = { "Hua" };
                            Assembly assembly
= Assembly.LoadFrom("DynamicInvokeTest.exe");
                            Type type
= assembly.GetType("DynamicInvokeTest.test");

                            object obj = Activator.CreateInstance(type);
                            Console.WriteLine(
"Class: {0}",type.ToString());
                            Console.WriteLine(
"Invoking method: {0}", y.Attributes["name"].Value);
                            type.InvokeMember(y.Attributes[
"name"].Value,
                                BindingFlags.InvokeMethod ,
                               
null,
                                obj,
                                argument);
                        }
                    }
                }
            }
            Console.ReadKey();
        }
    }

    public class test
    {
       
public void method1(string i)
        {
            Console.WriteLine(i.ToString());
        }

        public void method2(string name)
        {
            Console.WriteLine(
"Hello, {0}", name);
        }
    }

}

你可能觉得没什么,不就是 InvokeMember 嘛。但对我来说,能有这灵活性,是非常有用的。

这与真正的 rule engine 差十万九千里,不过我够用了。

 

output

 

后记:

做些没做过的事很兴奋,但这达不到真正能用的程度,还要加很多东西,不然极多局限。比如业务流程之间的依赖问题,又比如有条件时候要Parse然后evaluate,或者 rule chaining 的实现,而且。再经过一番搜索,我发现有人做了,用了 WF 的 rule engine 但不用它的 Workflow。我试试有空再贴出来吧。

http://www.richard-banks.org/2007/08/how-to-use-windows-workflow-rules.html 

抱歉!评论已关闭.