代码改变世界

Caliburn笔记-Action的创建(wpf框架)

2009-12-25 11:24  Clingingboy  阅读(1264)  评论(0编辑  收藏  举报
    若一个对象被设置成为DataContext,该对象的方法称之为Action,caliburn通过附加属性来绑定这些Action,首先则需要获取绑定对象的方法.如下示例对象,则有4个方法.
[Rescue("GeneralRescue")]
public class Calculator
{
    //Note: This rescue catches exceptions thrown by this method.
    //[Rescue("ActionSpecificRescue")]
    //Note: Preview indicates something that will happen before execution of the action.
    //Note: If AffectsTriggers = false, then this filter will not effect the state of the UI in real time.
   // [Preview("CanDivide")]
    //Note: The return value is bound to the UI if present.
    public int Divide(int left, int right)
    {
        return left / right;
    }

    //Note: See Preview filter.
    public bool CanDivide(int left, int right)
    {
        return right != 0;
    }

    //Note: See class level rescue filter.
    public void GeneralRescue(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

    //Note: See rescue filter on Divide method.
    public void ActionSpecificRescue(Exception ex)
    {
        MessageBox.Show("Divide Action: " + ex.Message);
    }
}


Action只包含公开方法,并不包含属性与事件等,所以需要对象成员进行过滤.如下逻辑

protected virtual IEnumerable<IGrouping<string, MethodInfo>> SelectMethods(Type targetType)
{
    return
        from method in targetType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
        where method.DeclaringType != typeof(object)
              && !method.ContainsGenericParameters
              && !method.Name.StartsWith("get_")
              && !method.Name.StartsWith("set_")
              && !method.Name.StartsWith("remove_")
              && !method.Name.StartsWith("add_")
              && method.GetParameters().All(x => !x.IsOut)
        group method by method.Name
        into groups
            select groups;
}

方法与Action的转换


完成方法过滤后,为了添加功能,还要对方法进行转换.

首先根据方法,创建一个IMethod.然后创建Action.

当然Action还有其他功能,这里分为同步与异步.

protected virtual IAction CreateAction(IActionHost host, MethodInfo methodInfo)
{
    var method = _methodFactory.CreateFrom(methodInfo);
    var asyncAtt = method.GetMetadata<AsyncActionAttribute>();

    var filters = host.GetFilterManager(method);

    TryAddCanExecute(filters, method);

    if(asyncAtt == null)
        return new SynchronousAction(method, _messageBinder, filters);
    return new AsynchronousAction(method, _messageBinder, filters, asyncAtt.BlockInteraction);
}


创建好以后再将其保存,创建过程由实现IActionFactory接口的ActionFactory完成.

image

public IEnumerable<IAction> CreateFor(IActionHost host)
{
    var actions = new List<IAction>();
    var methodGroups = SelectMethods(host.TargetType);

    foreach(var methodGroup in methodGroups)
    {
        var methodList = methodGroup.ToList();

        if(methodList.Count == 1)
            actions.Add(CreateAction(host, methodList[0]));
        else
        {
            var overloadedAction = new OverloadedAction(methodGroup.Key);

            foreach(var methodInfo in methodList)
            {
                overloadedAction.AddOverload(CreateAction(host, methodInfo));
            }

            actions.Add(overloadedAction);
        }
    }

    return actions;
}