I managed to do it by keeping a WorkflowInstanceProxy
, as suggested here:
public class WriteProcessParameters : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
WorkflowInstanceProxy proxy = context.GetExtension<WorkflowInstanceInfo>().GetProxy();
Activity root = proxy.WorkflowDefinition;
Dictionary<string, ProcessParameter> processParams = WorkflowHelpers.GetProcessParameters(root);
// Serialize processParams somehow...
}
protected override void CacheMetadata(CodeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
metadata.AddDefaultExtensionProvider<WorkflowInstanceInfo>(() => new WorkflowInstanceInfo());
}
private class WorkflowInstanceInfo : IWorkflowInstanceExtension
{
private WorkflowInstanceProxy m_proxy;
public IEnumerable<object> GetAdditionalExtensions() { yield break; }
public void SetInstance(WorkflowInstanceProxy instance) { this.m_proxy = instance; }
public WorkflowInstanceProxy GetProxy() { return m_proxy; }
}
}
That worked in my toy test, but not in an actual workflow (not sure why). So I ended up reading properties, like this:
public InArgument<string> Filename { get; set; }
protected override void Execute(CodeActivityContext context)
{
var propDescriptors = context.DataContext.GetProperties().Cast<PropertyDescriptor>();
var props = new Dictionary<string, object>();
foreach (var propDesc in propDescriptors.OrderBy(p => p.Name))
{
object value = propDesc.GetValue(context.DataContext);
if (value == null)
{
var converter = TypeDescriptor.GetConverter(propDesc.PropertyType);
if (converter.CanConvertTo(propDesc.PropertyType))
{
value = converter.ConvertTo(value, propDesc.PropertyType); // Known case: null string
}
else
{
continue; // Known case: RunTestParameters
}
}
else
{
if (!value.GetType().IsVisible || !value.GetType().IsSerializable)
{
continue;
}
}
props.Add(propDesc.Name, value);
}
File.WriteAllText(Filename.Get(context), WorkflowHelpers.SerializeProcessParameters(props));
}