【问题标题】:Retrieve Arguments of a Workflow (with default values)?检索工作流的参数(使用默认值)?
【发布时间】:2012-01-11 17:18:01
【问题描述】:

Given 是一个针对网站的 Workflow Foundation 4 运行时 ;)

我们需要获取工作流的参数以向用户显示编辑器以输入参数。为此,我们需要所有具有名称、类型和默认值的参数,以及是否需要参数的指示。

工作流存储为 XAML 文件。

如何做到这一点?数据似乎在活动元数据中,这似乎在工作流程之外不可用。另外,Workflow Engine ModelService 是针对 Designer 的,开销很大。

有什么简单的方法可以检索这些信息?

【问题讨论】:

    标签: workflow-foundation-4


    【解决方案1】:

    我已经做过类似的事情了。如果您想要通用方法,反射可能是您最好(也是唯一)的选择。

    // Just an holder for InArgument informations
    class InArgumentInfo
    {
        public string InArgumentName { get; set; }
        public string InArgumentDescription { get; set; }
        public bool InArgumentIsRequired { get; set; }
    }
    
    static ICollection<InArgumentInfo> GetInArgumentsInfos(Activity activity)
    {
        var properties = activity.GetType()
            .GetProperties()
            .Where(p => typeof(InArgument).IsAssignableFrom(p.PropertyType))
            .ToList();
    
        var argumentsCollection = new Collection<InArgumentInfo>();
    
        foreach (var property in properties)
        {
            var descAttribute = property
                .GetCustomAttributes(false)
                .OfType<DescriptionAttribute>()
                .FirstOrDefault();
    
            string description = descAttribute != null && !string.IsNullOrEmpty(descAttribute.Description) ?
                descAttribute.Description :
                string.Empty;
    
            bool isRequired = property
                .GetCustomAttributes(false)
                .OfType<RequiredArgumentAttribute>()
                .Any();
    
            argumentsCollection.Add(new InArgumentInfo
            {
                InArgumentName = property.Name,
                InArgumentDescription = description,
                InArgumentIsRequired = isRequired
            });
        }
    
        return argumentsCollection;
    }
    

    这样,您不仅可以检索参数的名称,还可以检索参数属性所保存的其他信息。例如,我选择通过 [Description] 属性为参数提供一个用户友好的名称(例如,用户看到“我的属性名称”而不是 MyPropertyName)。

    注意:如果你能保证你的activity是ActivityBuilder或者DynamicActivity,它们都有Properties属性可以使用,但是原理是一样的。

    【讨论】:

    • +1。您可以重用 DynamicActivityProperty(众所周知并保存所有这些信息)并创建一个方法来检查是 ActivityBuilder 还是 DynamicActivity 并返回 Properties 道具,在其他情况下使用反射来获取道具。 ;]
    • 当然,这是一个选项。我的猜测是 Properties 属性也在幕后使用反射。 DynamicActivity 实现ICustomTypeDescriptor
    【解决方案2】:

    将其加载为 DynamicActivity 并遍历 Properties 属性

    var dynamicActivity = ActivityXamlServices.Load(foo) as DynamicActivity
    foreach(DynamicActivityProperty prop in dynamicActivity.Properties)
    {
       // ...
    }
    

    更新:缺少默认值部分

    foreach (var prop in dynamicActivity .Properties)
    {
        object defaultValue;
        if (prop.Value == null)
        {
            defaultValue = null;
        }
        else
        {
            Type genericTypeDefinition = prop.Type.GetGenericTypeDefinition();
            if (genericTypeDefinition == typeof(InArgument<>) || genericTypeDefinition == typeof(InOutArgument<>))
            {
                var valueProp = prop.Value.GetType().GetProperty("Expression", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly);
                var expression = valueProp.GetValue(prop.Value, null);
    
                var expressionValueProp = expression.GetType().GetProperty("Value");
                defaultValue = expressionValueProp.GetValue(expression, null);
            }
        }
    }
    

    不完全保证,您需要做一些检查。

    【讨论】:

    • ActivityDynamicActivity 的转换无效。
    • 你确定吗?动态活动:活动。此活动是通过您的工作流设计器上的 ActivityBuilder 创建的?
    • 如果是通过代码创建的CustomCodeActivity呢?该演员表并非始终有效。
    • 我以为他正在加载一个带有 XAML 参数的活动,因为他说的是“工作流程”(整个工作流程),所以我推测他正在加载一个在 ActivityBuilder 上创建的动态活动,并在参数选项卡中创建了参数.
    • 我不是 OP,但它当然很有用。这是一个有效的选项,但前提是您确保原始活动是 ActivityBuilderDynamicActivity 而不是始终为真。
    猜你喜欢
    • 2012-08-01
    • 1970-01-01
    • 2011-12-19
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-19
    • 1970-01-01
    相关资源
    最近更新 更多