static void ExtractXamlDirectAssignments(XamlManipulationGroupNode manipGrp, XamlManipulationGroupNode xamlDirectAssignmentsNode, XamlManipulationGroupNode standardAssignmentsNode) { foreach (var manip in manipGrp.Children) { if (manip is XamlManipulationGroupNode nestedGrp) { ExtractXamlDirectAssignments(nestedGrp, xamlDirectAssignmentsNode, standardAssignmentsNode); } else if (manip is XamlPropertyAssignmentNode assign) { var xamlDirectSetters = assign.PossibleSetters.OfType <IXamlDirectSetter>().ToList(); if (xamlDirectSetters.Count != 0) { assign.PossibleSetters.Clear(); assign.PossibleSetters.AddRange(xamlDirectSetters); xamlDirectAssignmentsNode.Children.Add(assign); } else { standardAssignmentsNode.Children.Add(assign); } } else { standardAssignmentsNode.Children.Add(manip); } } }
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) { if (node is XamlValueWithManipulationNode valWithManip && TryGetNewObjectNodeForXamlDirect(valWithManip, out var newObj) && newObj.Arguments.Count == 0) { if (!(valWithManip.Manipulation is XamlObjectInitializationNode init) || !(init.Manipulation is XamlManipulationGroupNode manipGrp)) { throw new XamlParseException( "Unable to find the object initialization node inside object creation.", node); } IXamlType objType = newObj.Type.GetClrType(); if (objType.Assembly != context.GetWinUITypes().WinUIControlsAssembly) { // Only built-in controls have XamlDirect support. // Remove the XamlDirect setters since XamlDirect isn't worth using once the object // is created and return. RemoveXamlDirectSettersFromAssignments(manipGrp); return(node); } IXamlField typeIndex = context.GetWinUITypes().XamlTypeIndex.GetAllFields().FirstOrDefault(fld => fld.Name == objType.Name); if (typeIndex is null) { // We didn't find a matching type index, so we can't use XamlDirect. // Remove the XamlDirect setters since XamlDirect isn't worth using once the object // is created and return. RemoveXamlDirectSettersFromAssignments(manipGrp); return(node); } IXamlAstValueNode constructedObjNode = new XamlDirectNewObjectNode(newObj, context.GetWinUITypes().IXamlDirectObject, typeIndex); var xamlDirectAssignmentsNode = new XamlManipulationGroupNode(constructedObjNode); var standardAssignmentsNode = new XamlManipulationGroupNode(constructedObjNode); ExtractXamlDirectAssignments(manipGrp, xamlDirectAssignmentsNode, standardAssignmentsNode); if (xamlDirectAssignmentsNode.Children.Count != 0) { constructedObjNode = new XamlValueWithManipulationNode(constructedObjNode, constructedObjNode, xamlDirectAssignmentsNode); } if (standardAssignmentsNode.Children.Count == 0) { node = new XamlObjectFromDirectObjectNode(constructedObjNode, newObj.Type); } else { valWithManip.Value = new XamlObjectFromDirectObjectNode(constructedObjNode, newObj.Type); init.Manipulation = standardAssignmentsNode; } } return(node);
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) { var usableAttrs = context.Configuration.TypeMappings.UsableDuringInitializationAttributes; if (!(usableAttrs?.Count > 0)) { return(node); } bool UsableDuringInitialization(IXamlType type) { foreach (var attr in type.CustomAttributes) { foreach (var attrType in usableAttrs) { if (attr.Type.Equals(attrType)) { return(attr.Parameters.Count == 0 || attr.Parameters[0] as bool? == true); } } } if (type.BaseType != null) { return(UsableDuringInitialization(type.BaseType)); } return(false); } bool TryConvert( IXamlAstValueNode checkedNode, out IXamlAstValueNode value, out IXamlAstManipulationNode deferred) { value = null; deferred = null; if (!(checkedNode is XamlValueWithManipulationNode manipulation && manipulation.Manipulation is XamlObjectInitializationNode initializer && UsableDuringInitialization(manipulation.Value.Type.GetClrType()))) { return(false); } initializer.SkipBeginInit = true; var local = new XamlAstCompilerLocalNode(manipulation.Value, manipulation.Value.Type.GetClrTypeReference()); value = new XamlValueNodeWithBeginInit(new XamlAstLocalInitializationNodeEmitter(local, manipulation.Value, local)); deferred = new XamlAstManipulationImperativeNode(initializer, new XamlAstImperativeValueManipulation(initializer, local, initializer)); return(true); } if (node is XamlPropertyAssignmentNode assignment) { if (!TryConvert(assignment.Values.Last(), out var nvalue, out var deferred)) { return(node); } assignment.Values[assignment.Values.Count - 1] = nvalue; return(new XamlManipulationGroupNode(assignment) { Children = { assignment, deferred } }); } else if (node is XamlNoReturnMethodCallNode call) { var deferredNodes = new List <IXamlAstManipulationNode>(); for (var c = 0; c < call.Arguments.Count; c++) { var arg = call.Arguments[c]; if (TryConvert(arg, out var narg, out var deferred)) { call.Arguments[c] = narg; deferredNodes.Add(deferred); } } if (deferredNodes.Count != 0) { var grp = new XamlManipulationGroupNode(call); grp.Children.Add(call); grp.Children.AddRange(deferredNodes); return(grp); } } return(node); }