以前没干过类似的,做反射也只限于复制属性,到处问别人但没有完全符合我要求我想法的。看看我的问题先:
不知道从什么时候开始,在业务层,做设计时候,我的业务对象和他们的方法,是分开写在不同的类和接口。这样设计好像有个名字的,那是题外话。但是,当一个业务对象与另一个业务对象,有交互时候,这些交互的方法应该写在哪里,对应的验证方法又放哪里?举个例,销售订单,销售发票,两个业务对象肯定有交互,操作时,销售发票可以是从销售订单生成,也可以创建了销售发票然后用订单的信息填满。我的做法是,再加一层,做业务逻辑,来操作这些业务对象和调用他们的方法。
另一个更简单的例子,如下图:
导入档案写入记录(第三方),做配对后映射到本域业务对象,写入,最后返回写入结果。其他业务流程也会调用到相同业务的方法,只是目的、顺序等有可能不一样。
这样我也 ok 的了,不过,如果这些操作顺序有改变,就要改“Process" 那一层了,改代码和重新编译。这些情况特别在一些商业逻辑上,经常发生,变动频繁。以前写的财务核算模块,核算规则不停的随着组织架构和成本分摊方式变化而需要改动,就是一个实例。
我希望,用 XML 定义业务流程的行为,通过改 XML(甚至是弄个界面让用户自己改),要能做到这些改动。这就是我想做的事。
最初第一想到的就是用 jBPM ( .Net 版),或者 Workflow Foundation,但感觉大材小用,有朋友介绍 Drools,分别不大。然后我上 stackoverflow 问,有位大哥说来说去都是叫我 IoC,然后我想了一下,容器还不是一样用反射,那我自己写也可以呀。
反射上面说了我不是很熟悉,弄了个简单的试验,果然能做到,如下:
<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.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 差十万九千里,不过我够用了。
后记:
做些没做过的事很兴奋,但这达不到真正能用的程度,还要加很多东西,不然极多局限。比如业务流程之间的依赖问题,又比如有条件时候要Parse然后evaluate,或者 rule chaining 的实现,而且。再经过一番搜索,我发现有人做了,用了 WF 的 rule engine 但不用它的 Workflow。我试试有空再贴出来吧。
http://www.richard-banks.org/2007/08/how-to-use-windows-workflow-rules.html