Let's say I have a workflow created progrmatically like this
ActivityBuilder<int> ab = new ActivityBuilder<int>();
ab.Name = "Add";
ab.Properties.Add(new DynamicActivityProperty {Name = "Operand1", Type = typeof (InArgument<int>)});
ab.Properties.Add(new DynamicActivityProperty {Name = "Operand2", Type = typeof (InArgument<int>)});
ab.Implementation = new Sequence
{
Activities =
{
new WriteLine
{
Text =
new VisualBasicValue<string>(
"Operand1.ToString() + \" + \" + Operand2.ToString()")
}
}
};
One way I know to execute it is to first serialize the ActivityBuilder object into XAML. Next, load the serialized XAML using ActivityXamlServices. Create a dictionary for parameters. Execute it using WorkflowInvoker or WorkflowApplication
Is there any way to execute this workflow without the need to convert/serialize activity builder to XAML?
WorkflowApplication and WorkflowInvoker takes an Activity as input for execution. Can I somehow use activityBuilder.Implementation directly with WorkflowApplication or WorkflowInvoker?
Why I want this? Because we have a workflow designer which user uses to create and execute workflow. User also creates workflow progrmatically. Workflow can be up to 80MB in size. This is hurting application's memory due to serialization and de-serialization of 80MB files to and from XAML. I want to somehow skip this step and directly execute activity.
Does it makes sense?
No need to use an ActivityBuilder, just create the activities you want and execute them.
var wf = new Sequence()
{
Variables =
{
new Variable<int>("Operand1", 7),
new Variable<int>("Operand2", 42)
},
Activities =
{
new WriteLine
{
Text =
new VisualBasicValue<string>(
"Operand1 & \" + \" & Operand2")
}
}
};
WorkflowInvoker.Invoke(wf);
An example using DynamicActivityProperty:
var wf = new DynamicActivity<int>
{
Properties =
{
new DynamicActivityProperty { Name = "Operand1", Type = typeof(InArgument<int>) },
new DynamicActivityProperty { Name = "Operand2", Type = typeof(InArgument<int>) }
},
Implementation = () => new Sequence()
{
Activities =
{
new WriteLine
{
Text =
new VisualBasicValue<string>(
"Operand1 & \" + \" & Operand2")
},
new Assign<int>
{
To = new ArgumentReference<int> { ArgumentName = "Result" },
Value = new VisualBasicValue<int>("Operand1 + Operand2")
}
}
}
};
var inputs = new Dictionary<string, object>();
inputs["Operand1"] = 7;
inputs["Operand2"] = 42;
var output = WorkflowInvoker.Invoke(wf, inputs);
Console.WriteLine(output);
Related
If I was to use the high level model, I might try something like this:
public async void GetBooksData()
{
GetItemRequest request = new GetItemRequest
{
TableName = "Customer",
Key = new Dictionary<string, AttributeValue>
{
{"UserName", new AttributeValue{S="a"} },
{"BookNum", new AttributeValue { S = starts_with(queryTerm)} }
}
};
try
{
var response = await client.GetItemAsync(request);
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
if (response.Item.Count > 0)
{
foreach (var item in response.Item)
{
MessageBox.Show("Value : \n" + item.Value.S);
}
}
}
}
catch (InternalServerErrorException iee)
{
MessageBox.Show(iee);
}
}
I need to use the method 'begins_with' for getting 2 items what UserName is 'a' and the BookNum are book_1 and book_2. This is possible in the high level interface in Java. As an example as to what can be done on the range key in Java:
public List<Comment> allForItemWithMinRating(String itemId, int minRating) {
Comment comment = new Comment();
comment.setItemId(itemId);
Condition condition = new Condition()
.withComparisonOperator(ComparisonOperator.GE)
.withAttributeValueList(
new AttributeValue()
.withN(Integer.toString(minRating)));
DynamoDBQueryExpression<Comment> queryExpression
= new DynamoDBQueryExpression<Comment>()
.withHashKeyValues(comment)
.withRangeKeyCondition(
"rating",
condition
)
.withScanIndexForward(false);
return mapper.query(Comment.class, queryExpression);
}
In the low level interface for C# you can achieve this as so:
var requestDynamodb = new QueryRequest
{
TableName = "GroupEdEntries",
KeyConditionExpression = "partition_key = :s_Id and begins_with(sort_key, :sort)",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":s_Id", new AttributeValue { S = my_id }},
{":sort", new AttributeValue { S = sort_key_starts_with }}
},
ConsistentRead = true
};
var results = await client.QueryAsync(requestDynamodb);
where the keys are called partition_key and sort_key. However, this returns the results as attribute values, which then need to be converted into POCOs one property at a time. It requires using reflection and is made more complicated using converters. It seems strange that this fundamental functionality (as well as other functionality) isn't supported in the C# SDK.
I ended up using reflection to create the tables based on the attributes, when this is also supported by default in Java. Am I missing a high level API for C#?
It's a bit of a different syntax and I can't find it documented anywhere (other than in code comments), but this works for me:
string partition_key = "123";
string sort_key_starts_with = "#type"
List<object> queryVal = new List<object>();
queryVal.Add(sort_key_starts_with);
var myQuery = context.QueryAsync<GroupEdEntry>(partition_key, QueryOperator.BeginsWith, queryVal);
var queryResult = await myQuery.GetRemainingAsync();
Currently having an issue creating a reusable object that I will need to use in a JSON construct string function.
Currently I have the following to create the bulk of the JSON string:
var data = new
{
record = new
{
value1 = Row.value1,
value2 = Row.value2,
form_values = new Dictionary<string, string>()
}
};
data.record.form_values["833b"] = Row.value3.ToString();
data.record.form_values["98wq"] = BuildMultiSelectList(Row.value3.ToString());
public object BuildMultiSelectList(string datavalue)
{
var choicelist = new {
choice_values: [datavalue],
other_values: [],
};
return choicelist;
}
The top half all works fine, though the function BuildMultiSelectList is giving errors such as "choice_values" does not exist in the current context and datavalue does not exist in the current context.
Any insight on why this has gone a bit rouge will be appreciated.
May be you are just mixing colon : with =?
var choicelist = new {
choice_values = new string[] {datavalue},
other_values = new[] {},
};
I am trying to set the value of object property which is of type List and initialise it by using a foreach to add the items to the list e.g.
var sessionPlanner = new SessionPlannerDTO()
{
Age = "",
NumberOfPlayers = session.numberOfPlayers.Value,
MedicalInformation = "",
PlayerNeeds = "",
SessionDate = session.daySessionDate.Value,
Location = session.Location.locationName,
PracticeView = new List<PracticeViewDTO>(foreach(var practice in session.Sessions){
new PracticeViewDTO(){AbilityLevel = practice.ActivityPlan.abilityLevel.Value,
ActivityUrl = practice.ActivityPlan.activityUrl,
EquipmentNeeds = practice.ActivityPlan.equipmentNeeds,
FacilityNeeds = practice.ActivityPlan.activityNeeds,
HealthAndSafety = practice.ActivityPlan.healthAndSafetyIssues,
SessionTitle = practice.ActivityPlan.activityName
};
})
};
PracticeView is what I am trying to achieve by making it a list without doing the below:
var practiceViewList = new List<PracticeViewDTO>();
foreach(var practice in session.Sessions)
{
var practiceX = new PracticeViewDTO()
{
AbilityLevel = practice.ActivityPlan.abilityLevel.Value,
ActivityUrl = practice.ActivityPlan.activityUrl
};
practiceViewList.Add(practiceX);
}
You can't use other code than assignments in object or collection initializers. So your foreach() there won't compile.
Use session.Sessions.Select() to map the source entities to your DTO, and ToList() to create a list of the result:
sessionPlanner = new SessionPlannerDTO
{
Age = "",
// ...
PracticeView = session.Sessions.Select(s =>
new PracticeViewDTO
{
AbilityLevel = s.ActivityPlan.abilityLevel.Value,
// ...
}).ToList()
};
You also may want to consider using AutoMapper, instead of hand-writing mapping code.
I am building a workflow in my code, and I don't know how I can add a simple (While) condition. Tried to figure out how, but no luck with it, search on the internet but no luck either.
This is a simplified version of what I am trying to do:
ActivityBuilder ab = new ActivityBuilder();
ab.Implementation = new Sequence()
{
Variables =
{
new Variable<int>("StepNo", 0)
},
Activities =
{
new While()
{
Condition = <the_condition>
Body =
{
//Some logic here and the StepNo is increased
}
}
}
}
The While condition should be something like "StepNo < 10". Any idea how can this be made?
var stepNo = new Variable<int>("stepNo", 0);
var activity = new Sequence
{
Variables =
{
stepNo
},
Activities =
{
new While
{
Condition = new LessThan<int,int,bool>
{
Left = stepNo,
Right = 10
},
Body = new Sequence
{
Activities =
{
new Assign<int>
{
To = stepNo,
Value = new Add<int, int, int>
{
Left = stepNo,
Right = 1
}
},
new WriteLine
{
Text = new VisualBasicValue<string>("\"Step: \" & stepNo")
}
}
}
}
}
};
Or a version without expression activities but only with VisualBasicValue, which is also an activity:
var stepNo = new Variable<int>("stepNo", 0);
var activity = new Sequence
{
Variables =
{
stepNo
},
Activities =
{
new While
{
Condition = new VisualBasicValue<bool>("stepNo < 10"),
Body = new Sequence
{
Activities =
{
new Assign<int>
{
To = stepNo,
Value = new VisualBasicValue<int>("stepNo + 1")
},
new WriteLine
{
Text = new VisualBasicValue<string>("\"Step: \" & stepNo")
}
}
}
}
}
};
I have a number of objects that I need to create and add to an array. However the code below seems dirty and difficult to maintain in the long run. What I'm thinking is, I should store the Name and Value properties in a table and build each comCommand object at runtime.
However, I'm not exactly sure what the best method to about doing this... Reflection, Activator.CreateInstance or some kind of object factory?
Thanks in advance.
var engine = new comCommand() { commandName = "-e", commandValue = "PNetTNative" };
var outputFile = new comCommand() { commandName = "-f", commandValue = OutputFile };
var groupSize = new comCommand() { commandName = "-GroupSizeParamInput1ParamsIn", commandValue = GroupSize };
var pagesPerSheet = new comCommand() { commandName = "-PagesPerSheetParamInput1ParamsIn", commandValue = PagesPerSheet };
var outputFileName = new comCommand { commandName = "-OutputFileNameParamInput1ParamsIn", commandValue = OutputFileName };
var duplex = new comCommand { commandName = "-DuplexParamInput1ParamsIn", commandValue = Duplex };
var processId = new comCommand { commandName = "-ProcessIDParamInput1ParamsIn", commandValue = ProcessID };
var request = new comRunWorkFlowReq();
request.command = new[] { engine, outputFile, groupSize, pagesPerSheet, outputFileName, duplex, processId };
Create a command constructor (as Kirk suggested) and keep it as you have: multiple comCommand("-e","PNetTNative") etc calls.
The reason for keeping it in code is you get compiler-time type and error checking... Yes, you can do it at runtime (various methods) but for just 7 declarations, it's best to keep it at compile time.