事件与委托的原理和应用 参考:
1.(最下面的:Delegates.cs)首先声明 一个命名空间, 把全部的委托都声明在这里。 委托的参数有可能是一个类型,
这个类型可是是model类型。
这里设置为 public class CallbackArgs : EventArgs
Args 参数 继承 自EventArgs 类, 声明类中的值与属性。
public class CallbackArgs : EventArgs
{
private string callbackId;
public CallbackArgs(string callbackId)
{
this.callbackId = callbackId;
}
public string CallbackId
{
get
{
return callbackId;
}
}
}
2. 总父类声明事件。
public interface IEvidence : IComparable, ICloneable
{
event RuleEngine.ChangedHandler Changed;
event RuleEngine.EvidenceLookupHandler EvidenceLookup;
event RuleEngine.ModelLookupHandler ModelLookup;
event RuleEngine.CallbackHandler CallbackLookup;
3.AEvidence : IEvidence 因为所有的类都是与AEvidence 结合做操作的。
所以AEvidence 中的事件覆盖IEvidence 中的事件。
/// </summary>
public abstract class AEvidence : IEvidence
{
private event ModelLookupHandler modelLookup;/
private event ChangedHandler changed;/
private event EvidenceLookupHandler evidenceLookup;
private event CallbackHandler callbackLookup;
4.AEvidence 类中定义大量虚方法,并且把事件进行封装
事件本身即是 委托的对象的封装(属性)。 这些对这个事件再次封装(属性)。 供进一步调用。 提供移出方法。
public virtual event ChangedHandler Changed
{
add
{
changed = value;
}
remove
{
changed = null;
}
}
提供虚方法。 方法中调用事件(委托banding的方法)。 其他对象直接调用方法就可以达到调用事件的目的。
protected virtual void RaiseChanged(object sender, ChangedArgs args)
{
if (changed != null)
changed(sender, args);
}
5. 事实子类Fact 继承了AEvidence类
public class Fact : AEvidence, IFact
{
protected override void Value_Changed(object sender, ChangedArgs args)
{
RaiseChanged(this, args);
}
}
重写了AEvidence类中的方法。直接调用AEvidence类中的RaiseChanged函数。
RaiseChanged函数上面提到了,其实是去调用一个事件。
利用这种方式来避免 继承的子类对于父类的事件的变动。
6. Delegates.cs文件
using System; using System.Collections.Generic; using System.Text; using System.Xml; using RuleEngine.Evidence; namespace RuleEngine { /// <summary> ///对象改变状态 States that an object has changed /// </summary> /// <param name="sender"></param> /// <param name="args"></param> /// <returns></returns> public delegate void ChangedHandler(object sender, ChangedArgs args); /// <summary> ///查找IEvidence Requests the specified IEvidence /// </summary> /// <param name="sender"></param> /// <param name="args"></param> /// <returns></returns> public delegate IEvidence EvidenceLookupHandler(object sender, EvidenceLookupArgs args); /// <summary> /// 行为对应从一个时间到客户端 ActionCallback object fires off a event to the client /// </summary> /// <param name="sender">行为引发的事件action that caused the event</param> /// <param name="AssociatedFact">行为关联的事实 fact that this action is associated with</param> /// <returns>truthality of the callback</returns> public delegate void CallbackHandler(object sender, CallbackArgs args); /// <summary> ///XmlNode查找模型。 ///注意:一个模型应该是一个客户端提供的模型通过父节点的一个嵌套的事实。 ///</summary> /// <param name="sender"></param> /// <param name="ModelArgs"></param> /// <returns></returns> public delegate XmlNode ModelLookupHandler(object sender, ModelLookupArgs e); /// <summary> ///此委托类型的具体注册事件操作 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> /// <returns></returns> public delegate object RegisteredMethodHandler(object sender, EventArgs e); /// <summary> /// 证明查找事件参数定义 EvidenceLookupArgs /// </summary> public class EvidenceLookupArgs : EventArgs { private string key; public EvidenceLookupArgs(string Key) { key = Key; } public string Key { get { return key; } } } /// <summary> /// XML模型查找参数定义 /// </summary> public class ModelLookupArgs : EventArgs { private string key; public ModelLookupArgs(string Key) { key = Key; } public string Key { get { return key; } } } /// <summary> /// 改变状态事件参数定义 /// </summary> public class ChangedArgs : EventArgs { } /// <summary> /// 改变模型状态事件定义 /// </summary> public class ChangedModelArgs : ChangedArgs { private string modelId; public ChangedModelArgs(string modelId) { this.modelId = modelId; } public string ModelId { get { return modelId; } } } /// <summary> /// EventArgs请求中间List参数 EventArgs for requesting the mediator list /// </summary> public class MediatorListArgs : EventArgs { public MediatorListArgs() { } } /// <summary> ///模型更新事件参数 /// </summary> public class ModelUpdateArgs : EventArgs { private string modelId; public ModelUpdateArgs(string modelId) { this.modelId = modelId; } public string ModelId { get { return modelId; } } } /// <summary> /// 委托回调事件参数 /// </summary> public class CallbackArgs : EventArgs { private string callbackId; public CallbackArgs(string callbackId) { this.callbackId = callbackId; } public string CallbackId { get { return callbackId; } } } } |
7.具体执行部分
Decision.cs 首先绑定change的事件。
foreach (IEvidence evidence in evidenceCollection.Values) { evidence.CallbackLookup += RaiseCallback; evidence.EvidenceLookup += RaiseEvidenceLookup; evidence.ModelLookup += RaiseModelLookup; evidence.Changed += delegate(object sender, ChangedArgs args) { IEvidence evidence1 = (IEvidence)sender; if (!(evidence1 is IFact)) return; //找出这ifact模型 IFact fact = (IFact)evidence1; IEvidenceValue value = (IEvidenceValue)fact.ValueObject; string modelId = value.ModelId; //遍历所有ifacts并添加这些到相同的模型来执行列表 foreach(IEvidence evidence2 in evidenceCollection.Values) { //排除所有不IFact证据类型 if (!(evidence2 is IFact)) continue; //排除自己 if (evidence2.ID == evidence1.ID) continue; //排除所有那些不同的ifacts模型 if (evidence2.ValueObject.ModelId != modelId) continue; //加入list executionList.Add(evidence2); } }; } |
/// 函数--计算
/// </summary>
public override void Evaluate()
{
ExpressionEvaluator e = new ExpressionEvaluator();
e.GetEvidence += new EvidenceLookupHandler(RaiseEvidenceLookup);
e.Postfix = this.postfixExpression;
ExpressionEvaluator.Symbol o = e.Evaluate();
base.EvidenceValue.Reset(); //清空之前的值
//结果是IEvidenceValue类型,或者表达式为无效的,则抛出异常
IEvidenceValue result = o.value as IEvidenceValue;
//空返回退出
if (o.type == ExpressionEvaluator.Type.Invalid)
{
return;
}
//值被改变了则调用事件
if (base.Value.Equals(result.Value))
return;
base.Value = result.Value;//此方法,引发false时规则条件表达式中的引用为0
RaiseChanged(this, new ChangedArgs());
}
计算的最后,值得到之后。将会主动调用改变函数。 改变函数中调用绑定的change事件做操作。
即,与此规则相关的信息重新加载。
OK!
8. 核心流程
以规则为例。
上面的规则加载进来之后。
1.通过 表达式的计算 ExpressionEvaluator.Symbol o = e.Evaluate();
得到值,通过值判断,看是否改变。
2.通过值改变, 调用事件的 值改变方法。 执行重新加载规则相关信息的操作。
本人声明:沐海(http://my.oschina.net/mahaisong) 以上文章是经过本人设计实践和阅读其他文档得出。如果需要探讨或指教可以留言!欢迎交流!