@@ -217,30 +217,116 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo
217217 var sourceExpr = DynamicExpressionParser . ParseLambda ( new [ ] { stepParameter } , typeof ( object ) , output . Value ) ;
218218
219219 var dataParameter = Expression . Parameter ( dataType , "data" ) ;
220- Expression targetProperty ;
221220
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
225226 {
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 ) ;
229228 }
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 ( "[" ) )
231283 {
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" ) ;
235300
236301 Action < IStepBody , object > acn = ( pStep , pData ) =>
237302 {
303+ var targetExpr = Expression . Lambda ( memberExpression , dataParameter ) ;
304+ object data = targetExpr . Compile ( ) . DynamicInvoke ( pData ) ;
238305 object resolvedValue = sourceExpr . Compile ( ) . DynamicInvoke ( pStep ) ; ;
239- propertyInfo . SetValue ( pData , resolvedValue , new object [ ] { output . Key } ) ;
306+ propertyInfo . SetValue ( data , resolvedValue , new object [ ] { items [ 1 ] } ) ;
240307 } ;
241308
242309 step . Outputs . Add ( new ActionParameter < IStepBody , object > ( acn ) ) ;
310+ hasAddOutput = true ;
243311 }
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 ) ) ;
244330 }
245331 }
246332
0 commit comments