@@ -217,30 +217,116 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo
217
217
var sourceExpr = DynamicExpressionParser . ParseLambda ( new [ ] { stepParameter } , typeof ( object ) , output . Value ) ;
218
218
219
219
var dataParameter = Expression . Parameter ( dataType , "data" ) ;
220
- Expression targetProperty ;
221
220
222
- // Check if our datatype has a matching property
223
- var propertyInfo = dataType . GetProperty ( output . Key ) ;
224
- if ( propertyInfo != null )
221
+
222
+ if ( output . Key . Contains ( "." ) || output . Key . Contains ( "[" ) )
223
+ {
224
+ AttachNestedOutput ( output , step , source , sourceExpr , dataParameter ) ;
225
+ } else
225
226
{
226
- targetProperty = Expression . Property ( dataParameter , propertyInfo ) ;
227
- var targetExpr = Expression . Lambda ( targetProperty , dataParameter ) ;
228
- step . Outputs . Add ( new MemberMapParameter ( sourceExpr , targetExpr ) ) ;
227
+ AttachDirectlyOutput ( output , step , dataType , sourceExpr , dataParameter ) ;
229
228
}
230
- else
229
+ }
230
+ }
231
+
232
+ private void AttachDirectlyOutput ( KeyValuePair < string , string > output , WorkflowStep step , Type dataType , LambdaExpression sourceExpr , ParameterExpression dataParameter )
233
+ {
234
+ Expression targetProperty ;
235
+
236
+ // Check if our datatype has a matching property
237
+ var propertyInfo = dataType . GetProperty ( output . Key ) ;
238
+ if ( propertyInfo != null )
239
+ {
240
+ targetProperty = Expression . Property ( dataParameter , propertyInfo ) ;
241
+ var targetExpr = Expression . Lambda ( targetProperty , dataParameter ) ;
242
+ step . Outputs . Add ( new MemberMapParameter ( sourceExpr , targetExpr ) ) ;
243
+ }
244
+ else
245
+ {
246
+ // If we did not find a matching property try to find a Indexer with string parameter
247
+ propertyInfo = dataType . GetProperty ( "Item" ) ;
248
+ targetProperty = Expression . Property ( dataParameter , propertyInfo , Expression . Constant ( output . Key ) ) ;
249
+
250
+ Action < IStepBody , object > acn = ( pStep , pData ) =>
251
+ {
252
+ object resolvedValue = sourceExpr . Compile ( ) . DynamicInvoke ( pStep ) ; ;
253
+ propertyInfo . SetValue ( pData , resolvedValue , new object [ ] { output . Key } ) ;
254
+ } ;
255
+
256
+ step . Outputs . Add ( new ActionParameter < IStepBody , object > ( acn ) ) ;
257
+ }
258
+
259
+ }
260
+
261
+ private void AttachNestedOutput ( KeyValuePair < string , string > output , WorkflowStep step , StepSourceV1 source , LambdaExpression sourceExpr , ParameterExpression dataParameter )
262
+ {
263
+ PropertyInfo propertyInfo = null ;
264
+ String [ ] paths = output . Key . Split ( '.' ) ;
265
+
266
+ Expression targetProperty = dataParameter ;
267
+
268
+ bool hasAddOutput = false ;
269
+
270
+ foreach ( String propertyName in paths )
271
+ {
272
+ if ( hasAddOutput )
273
+ {
274
+ throw new ArgumentException ( $ "Unknown property for output { output . Key } on { source . Id } ") ;
275
+ }
276
+
277
+ if ( targetProperty == null )
278
+ {
279
+ break ;
280
+ }
281
+
282
+ if ( propertyName . Contains ( "[" ) )
231
283
{
232
- // If we did not find a matching property try to find a Indexer with string parameter
233
- propertyInfo = dataType . GetProperty ( "Item" ) ;
234
- targetProperty = Expression . Property ( dataParameter , propertyInfo , Expression . Constant ( output . Key ) ) ;
284
+ String [ ] items = propertyName . Split ( '[' ) ;
285
+
286
+ if ( items . Length != 2 )
287
+ {
288
+ throw new ArgumentException ( $ "Unknown property for output { output . Key } on { source . Id } ") ;
289
+ }
290
+
291
+ items [ 1 ] = items [ 1 ] . Trim ( ) . TrimEnd ( ']' ) . Trim ( ) . Trim ( '"' ) ;
292
+
293
+ MemberExpression memberExpression = Expression . Property ( targetProperty , items [ 0 ] ) ;
294
+
295
+ if ( memberExpression == null )
296
+ {
297
+ throw new ArgumentException ( $ "Unknown property for output { output . Key } on { source . Id } ") ;
298
+ }
299
+ propertyInfo = ( ( PropertyInfo ) memberExpression . Member ) . PropertyType . GetProperty ( "Item" ) ;
235
300
236
301
Action < IStepBody , object > acn = ( pStep , pData ) =>
237
302
{
303
+ var targetExpr = Expression . Lambda ( memberExpression , dataParameter ) ;
304
+ object data = targetExpr . Compile ( ) . DynamicInvoke ( pData ) ;
238
305
object resolvedValue = sourceExpr . Compile ( ) . DynamicInvoke ( pStep ) ; ;
239
- propertyInfo . SetValue ( pData , resolvedValue , new object [ ] { output . Key } ) ;
306
+ propertyInfo . SetValue ( data , resolvedValue , new object [ ] { items [ 1 ] } ) ;
240
307
} ;
241
308
242
309
step . Outputs . Add ( new ActionParameter < IStepBody , object > ( acn ) ) ;
310
+ hasAddOutput = true ;
243
311
}
312
+ else
313
+ {
314
+ try
315
+ {
316
+ targetProperty = Expression . Property ( targetProperty , propertyName ) ;
317
+ }
318
+ catch
319
+ {
320
+ targetProperty = null ;
321
+ break ;
322
+ }
323
+ }
324
+ }
325
+
326
+ if ( targetProperty != null && ! hasAddOutput )
327
+ {
328
+ var targetExpr = Expression . Lambda ( targetProperty , dataParameter ) ;
329
+ step . Outputs . Add ( new MemberMapParameter ( sourceExpr , targetExpr ) ) ;
244
330
}
245
331
}
246
332
0 commit comments