重新托管的 WF4 设计器中参数的默认值无法解析

问题描述 投票:0回答:2

重新托管设计器 (WF4) 的结果在向参数添加默认值时存在问题。其他所有情况似乎都运行良好。这是(几乎)空的工作流程的(删节的)xaml。

<Activity mc:Ignorable="sap" x:Class="{x:Null}" this:_b40c.NewArg="test" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" 
xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" 
xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:this="clr-namespace:" xmlns:twc="clr-namespace:Telogis.Workflow.CustomerApi;assembly=Telogis.Workflow.Activities" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <x:Members>
    <x:Property Name="AuthenticationHeader" Type="InArgument(twc:AuthenticationHeader)" />
    <x:Property Name="BaseTdeUri" Type="InArgument(x:Uri)" />
    <x:Property Name="NewArg" Type="InArgument(x:String)" />
  </x:Members>
  <sap:VirtualizedContainerService.HintSize>654,676</sap:VirtualizedContainerService.HintSize>
  <mva:VisualBasic.Settings>Assembly references and imported namespaces serialized as XML namespaces</mva:VisualBasic.Settings>
  <Flowchart />
</Activity>

具体来说,当添加默认值时,定义中添加了以下内容:

this:_b40c.NewArg="test"
xmlns:this="clr-namespace:"
xmlns:this="clr-namespace:"
无效,因为它不指向任何地方,并且无法使用
ActivityXamlServices.Load(stream);
进行解析(它抛出 XamlObjectWriterException: "'无法设置未知成员 '{clr-namespace:}_b40c.NewArg'。' ...) 无论参数的指定类型是什么,这似乎都会发生。

知道是什么原因造成的吗?

更新

我首先使用

ActivityBuilder
来利用该活动。这很好,但由于我没有为其提供名称,因此它必须生成一个密钥,在上面的示例中
_b40c
ActivityXamlServices.Load
处理这些键时遇到一些问题。然而,简单地为
ActivityBuilder
定义一个名称似乎就可以解决问题。

这仍然没有回答为什么它创建

xmlns:this="clr-namespace:"
而没有实际的命名空间。

c# .net xaml workflow-foundation-4 workflow-rehosting
2个回答
0
投票

您的工作流程 xaml 无效。我不确定你从哪里得到它或者它是如何进入这种状态的。

我可以这么说,因为

<Activity 
    x:Class="{x:Null}" 
    this:_b40c.NewArg="test"
    xmlns:this="clr-namespace:" 

clr 风格的命名空间声明无效。它应该读作

clr-namespace:Some.Namespace.In.The.Current.Assembly

clr-namespace:Some.Namespace;assembly=SomeAssemblyWithSomeNamespace

由于您的声明格式错误,XamlObjectWriter 无法解析 this xml 命名空间,以确定您的

_b40c
类型存在于哪个命名空间/程序集中。此外,这看起来也非常可疑。我以前从未见过
x:Class
设置为 null。这也让我觉得畸形。


0
投票

如果我理解得好的话 - 这是 WF Designer bug。

当我必须在自定义 WF 设计器中支持

InArgument<T>
的默认值定义时,我遇到了这个问题。我仍然对这个基本程序缺乏支持感到惊讶。

失败的原因有2个:

  1. {x:Null}
    属性中
    x:Class
    的定义
  2. xmlns:this
    属性定义无效
  3. 主要问题是Argument默认值的定义无效:
    this:_effe.MyArgument="asd"
    。参数默认值的定义应等于:
    MyXamlClassName.MyArgument="asd"

例如,如果您的

x:Class
定义为
x:Class="MyNamespace.MyClass"
,则参数定义应为
this:MyClass.MyArgument="asd"

我通过干预 XAML 保存过程解决了这个问题。打电话后

_workflowDesigner.Save(_editedFile);

我添加了这两行:

#region x:Class and Argument<T> default value issues solution
await CreateAttributeValue(_editedFile, ConstXClassAttributeName, typeof(App).Namespace + "." + Path.GetFileNameWithoutExtension(_editedFile));
// should finish first operation before second operation begins to avoid I/O exception
await CreateAttributeValue(_editedFile, ConstNamespaceAttributeName, ConstXamlClrNamespace + typeof(App).Namespace);
await RepairArgsAttributes(_editedFile);
#endregion

这些是方法定义:

/// <summary>
/// Reason of using of this method: bug in workflow designer. When you save your xaml file, WF Designer assign "{x:Null}" to x:Class attribute
/// Bug: In addition, if you want to set default value for your InArgument<T>, it defines attribute "this" (namespace declaration) with empty value. When you try to open your file, designer fails to parse XAML.
/// </summary>
/// <param name="editedFile"></param>
/// <param name="attribteName"></param>
/// <param name="attributeValueToReplace"></param>
private static async Task CreateAttributeValue(string editedFile, string attribteName, string attributeValueToReplace)
{
        XmlDocument xmlDoc = new XmlDocument();
        await Task.Run(() => xmlDoc.Load(editedFile));

        await Task.Run(() =>
        {
            var attributteToReplace = xmlDoc.FirstChild.Attributes?[attribteName];

            if (null != attributteToReplace)
            {
                xmlDoc.FirstChild.Attributes[attribteName].Value = attributeValueToReplace;
                xmlDoc.Save(editedFile);
            }
        });
}

/// <summary>
/// Bug in Workflow designer: workflow designer saves declaration for In/Out Arguments in invalid format. Means, that it is unable to open the same file it saved itself. This method fixes the Arguments declaration in XAML xmlns
/// </summary>
/// <param name="editedFile"></param>
/// <returns></returns>
private async Task RepairArgsAttributes(string editedFile)
{
    XmlDocument xmlDoc = new XmlDocument();
    await Task.Run(() => xmlDoc.Load(editedFile));

    await Task.Run(() =>
            {
                for (int i = 0; i < xmlDoc.FirstChild.Attributes.Count; i++)
                {
                    if (xmlDoc.FirstChild.Attributes[i].Name.StartsWith(ConstInvalidArgStarts))
                    {
                        string innvalidAttrName = xmlDoc.FirstChild.Attributes[i].Name;//extraction of full argument declaration in xmlns
                        string[] oldStrings = innvalidAttrName.Split('.');//extraction of arguemnt name string
                        string localName = Path.GetFileNameWithoutExtension(editedFile) + "." + oldStrings[1];//build valid argment declaration without perfix
                        string valueBackup = xmlDoc.FirstChild.Attributes[i].Value;//saving of default value of Arguemnt<T>
                        xmlDoc.FirstChild.Attributes.RemoveNamedItem(xmlDoc.FirstChild.Attributes[i].Name);//removal of invalid Argument declaration with default value. WARNING: when you remove attribute, at this moment you have another item at the place xmlDoc.FirstChild.Attributes[i]
                        //definition of new valid attribute requires: set separately attribute prefix, localName (not "name" - it causes invalid attribute definition) and valid namespace url (in our case it's namespace definition in "this")
                        XmlAttribute attr = xmlDoc.CreateAttribute(ConstArgPrefix, localName, xmlDoc.FirstChild.Attributes[ConstNamespaceAttributeName].Value);
                        attr.Value = valueBackup;
                        xmlDoc.FirstChild.Attributes.InsertBefore(attr, xmlDoc.FirstChild.Attributes[i]);//define new correct Argument declaration attribute at the same place where was invalid attribute. When you put valid attribute at the same place your recover valid order of attributes that was changed while removal of invalid attribute declaration
                    }
                }
                xmlDoc.Save(editedFile);

    });
}

常量定义为:

private const string ConstXClassAttributeName = "x:Class";
private const string ConstXamlClrNamespace = "clr-namespace:";
private const string ConstNamespaceAttributeName = "xmlns:this";
private const string ConstInvalidArgStarts = @"this:_";
private const string ConstArgPrefix = @"this";

此解决方案也应该可以解决您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.