wf 中关于 outArgument 的错误

发布于 2024-11-24 06:04:25 字数 1194 浏览 1 评论 0 原文

当我使用书签在活动中声明 OutArgument 时,出现以下错误!

“未提供所需活动参数‘Out-arg’的值”

这是我的代码:

public string BookmarkName = "bookmark1 NameBookmark";        

[RequiredArgument]
public OutArgument<String> Out_arg { get; set; }

protected override void Execute(NativeActivityContext context)
{
    context.CreateBookmark(BookmarkName, new BookmarkCallback(OnBookmarkCallback));

    // Out_arg = new System.Activities.OutArgument<System.String>((string)val);
    // new ArgumentReference<string>("Out_arg");
}

protected override bool CanInduceIdle
{
    get
    {
        return true;
    }
}

void OnBookmarkCallback(NativeActivityContext context, Bookmark bookmark, object val)
{
     // Out_arg = new System.Activities.OutArgument<System.String>((string)val);
     // Out_arg = new OutArgument<String>((string)val);
     // Out_arg = ((string)val);
     Out_arg = new OutArgument<string>(new VisualBasicReference<string>((string)val));
}

First result

第二个结果

谢谢。

I got the following error when I declare an OutArgument inside an activity using a bookmark!

"value of required activity argument 'Out-arg' was not supplied"

Here's my code:

public string BookmarkName = "bookmark1 NameBookmark";        

[RequiredArgument]
public OutArgument<String> Out_arg { get; set; }

protected override void Execute(NativeActivityContext context)
{
    context.CreateBookmark(BookmarkName, new BookmarkCallback(OnBookmarkCallback));

    // Out_arg = new System.Activities.OutArgument<System.String>((string)val);
    // new ArgumentReference<string>("Out_arg");
}

protected override bool CanInduceIdle
{
    get
    {
        return true;
    }
}

void OnBookmarkCallback(NativeActivityContext context, Bookmark bookmark, object val)
{
     // Out_arg = new System.Activities.OutArgument<System.String>((string)val);
     // Out_arg = new OutArgument<String>((string)val);
     // Out_arg = ((string)val);
     Out_arg = new OutArgument<string>(new VisualBasicReference<string>((string)val));
}

First result

Second result

thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

没有你我更好 2024-12-01 06:04:25

我感觉您是一位新的 .NET 开发人员。当您刚接触开发时,WF4 并不是最容易进入的东西。该框架使用了许多不明显的设计模式,只有经验丰富的开发人员才能掌握。我这么说并不是因为我很棒(尽管,坦白说……),而是因为文档还不清楚,而且还没有太多关于 WF4 的资源。

然而,您误解了 WF4 中如何处理 In/OutArguments。您必须在 设置参数>CacheMetadata 被调用,然后使用 设置和参数的 Get 方法来设置/获取参数的值在运行时。

WF4 参数模式是:工作流运行时需要知道您的活动计划做什么,并且必须为工作流提供一种方法来处理重要的动态数据(动态数据)在运行时发生变化)您的活动需要运行。工作流运行时必须在运行时存储这些数据并对其进行序列化/反序列化。

为了让工作流程执行此操作,它为您提供了 In/Out/InOutArguments(和变量),您可以在其中存储易失性数据。在调用CacheMetadata期间,工作流了解这些实例并准备您在运行时访问它们所需的设施。 如果您在调用 CacheMetadata 之后更改这些属性,工作流将无法再获取/设置/序列化/反序列化这些实例包含的数据

因此,您必须设置一次,并且永远不要再次更改这些实例。您可以通过构造函数或实现 IActivityTemplateFactory

下面是一个简单的示例:

public sealed class Negate : NativeActivity<bool>, IActivityTemplateFactory
{
    [RequiredArgument]
    public InArgument<bool> Input { get; set; }

    public Negate() 
    {
        // set it within the constructor option
        //Input = new InArgument<bool>();
    }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        metadata.AddArgument(Input);
        metadata.AddArgument(Result);
    }

    protected override void Execute(NativeActivityContext context)
    {
         // note the use of Get and Set methods
         Result.Set(context, !Input.Get(context));
    }

    Activity IActivityTemplateFactory.Create(DependencyObject target)
    { 
        // or we can set the Arguments here
        return new Negate 
        {
            Input = new InArgument<bool>(),
            Result = new OutArgument<bool>()
        };
    }
}

当 Activity 被拖放到设计图面上时,将调用 IActivityTemplateFactory.Create。一旦删除,参数就会被创建,这发生在调用 CacheMetadata 之前。恕我直言,这是配置这些的最佳方法。使用构造函数可能会导致一些意外的行为。请注意我们如何在 CacheMetadata 中告诉运行时我们希望运行时跟踪的属性。一旦调用该方法,我们就永远不会更改这些属性中保存的实例。我们只能对它们调用方法(例如 GetSet)。

编辑:下面是调用这些方法的简单示例。

  • 用户将 Activity 从工具箱中拖放到设计图面上
  • 调用 Create 方法(在设计图面上创建 Activity) 调用
  • CacheMetadata
  • 用户输入 Input CacheMetadata 的值
  • 调用
  • 用户构建解决方案
  • 调用 CacheMetadata
  • 用户运行解决
  • 方案创建工作流实例
  • CacheMetadata 被调用
  • 工作流执行
  • Execute 被调用
  • InArgument.Get 被调用
  • OutArgument.Set 被调用
  • 工作流完成执行

I get the feeling you're a new .NET developer. WF4 isn't exactly the easiest thing to jump into when you're new to development. There are a number of not-obvious design patterns which the framework uses, which only experienced developers will grasp. I say this not because I'm awesome (although, quite frankly...) but because the documentation isn't clear, and there aren't many resources out there about WF4 yet.

Nevertheless, you are misunderstanding how In/OutArguments are handled in WF4. You must set the argument prior to CacheMetadata is called, and then use the Set and Get methods of the argument to set/get the value of the argument at runtime.

The WF4 Arguments pattern is: The Workflow runtime needs to know what your Activity is planning to do and must provide a way for the Workflow to handle the important dynamic data (data which changes during runtime) your Activity needs to operate. The Workflow runtime must be in change of storing this data at runtime and serializing/deserializing it.

In order for the Workflow to do this, it gives you In/Out/InOutArguments (and Variables) in which you can store your volatile data. During the call to CacheMetadata, the Workflow learns about these instances and prepares the facilities needed for you to access them at runtime. If you make changes to these properties after the call to CacheMetadata, the Workflow can no longer get/set/serialize/deserialize the data these instances contain.

You therefore must set these once and never change these instances again. You can do this via the constructor or by implementing IActivityTemplateFactory.

Here's a simple example:

public sealed class Negate : NativeActivity<bool>, IActivityTemplateFactory
{
    [RequiredArgument]
    public InArgument<bool> Input { get; set; }

    public Negate() 
    {
        // set it within the constructor option
        //Input = new InArgument<bool>();
    }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        metadata.AddArgument(Input);
        metadata.AddArgument(Result);
    }

    protected override void Execute(NativeActivityContext context)
    {
         // note the use of Get and Set methods
         Result.Set(context, !Input.Get(context));
    }

    Activity IActivityTemplateFactory.Create(DependencyObject target)
    { 
        // or we can set the Arguments here
        return new Negate 
        {
            Input = new InArgument<bool>(),
            Result = new OutArgument<bool>()
        };
    }
}

IActivityTemplateFactory.Create is called when the Activity is dropped on the design surface. Once dropped, the Arguments are created, which happens before CacheMetadata is called. This is the best way to configure these, imho. Using the constructor can lead to some unexpected behavior. Note how we are telling the runtime in CacheMetadata about the properties we want the runtime to track for us. Once the method is called, we never change the instance held within those properties. We can only call methods (such as Get and Set) on them.

Edit: Here's a simple example of when these methods are called.

  • User drags Activity from the toolbox and drops it on the design surface
  • Create method is called (creates the Activity on the design surface)
  • CacheMetadata is called
  • User enters the value of Input
  • CacheMetadata is called
  • User builds the solution
  • CacheMetadata is called
  • User runs the solution
  • An instance of the workflow is created
  • CacheMetadata is called
  • Workflow executes
  • Execute is called
  • InArgument.Get is called
  • OutArgument.Set is called
  • Workflow completes execution
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文