public static bool TryCallAdd(XamlIlAstTransformationContext context, IXamlIlProperty targetProperty, IXamlIlType targetPropertyType, IXamlIlAstValueNode value, out IXamlIlAstManipulationNode rv) { var so = context.Configuration.WellKnownTypes.Object; rv = null; IXamlIlWrappedMethod FindAdderImpl(IXamlIlType targetType, IXamlIlType valueType, IXamlIlType keyType = null) { var candidates = targetType.FindMethods(m => !m.IsStatic && m.IsPublic && (m.Name == "Add" || m.Name.EndsWith(".Add"))).ToList(); bool CheckArg(IXamlIlType argType, bool allowObj) { if (allowObj && argType.Equals(so)) { return(true); } if (!allowObj && !argType.Equals(so) && argType.IsAssignableFrom(valueType)) { return(true); } return(false); } foreach (var allowObj in new[] { false, true }) { foreach (var m in candidates) { if (keyType == null && m.Parameters.Count == 1 && CheckArg(m.Parameters[0], allowObj)) { return(new XamlIlWrappedMethod(m)); } if (keyType != null && m.Parameters.Count == 2 && m.Parameters[0].IsAssignableFrom(keyType) && CheckArg(m.Parameters[1], allowObj)) { return(new XamlIlWrappedMethod(m)); } } } return(null); } IXamlIlWrappedMethod FindAdderWithCast(IXamlIlType originalType, IXamlIlType newTargetType, IXamlIlType valueType) { var m = FindAdderImpl(newTargetType, valueType); if (m == null) { return(null); } return(new XamlIlWrappedMethodWithCasts(m, new[] { originalType, m.ParametersWithThis[1] })); } IXamlIlWrappedMethod FindAdder(IXamlIlType valueType, IXamlIlType keyType = null) { if (keyType == null) { if (targetPropertyType.Equals(context.Configuration.WellKnownTypes.IEnumerable)) { return(FindAdderWithCast(targetPropertyType, context.Configuration.WellKnownTypes.IList, valueType)); } if (targetPropertyType.GenericTypeDefinition?.Equals(context.Configuration.WellKnownTypes .IEnumerableT) == true) { return(FindAdderWithCast( targetPropertyType, context.Configuration.WellKnownTypes.IListOfT .MakeGenericType(targetPropertyType.GenericArguments[0]), valueType)); } } return(FindAdderImpl(targetPropertyType, valueType, keyType)); } if (TryConvertMarkupExtension(context, value, targetProperty, out var ext)) { var adder = FindAdder(ext.ProvideValue.ReturnType); if (adder != null) { ext.Manipulation = adder; rv = ext; return(true); } } else { var vtype = value.Type.GetClrType(); IXamlIlAstValueNode keyNode = null; bool IsKeyDirective(object node) => node is XamlIlAstXmlDirective d && d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Key"; void ProcessDirective(object d) { var directive = (XamlIlAstXmlDirective)d; if (directive.Values.Count != 1) { throw new XamlIlParseException("Invalid number of arguments for x:Key directive", directive); } keyNode = directive.Values[0]; } void ProcessDirectiveCandidateList(IList nodes) { var d = nodes.OfType <object>().FirstOrDefault(IsKeyDirective); if (d != null) { ProcessDirective(d); nodes.Remove(d); } } IXamlIlAstManipulationNode VisitManipulationNode(IXamlIlAstManipulationNode man) { if (IsKeyDirective(man)) { ProcessDirective(man); return(new XamlIlManipulationGroupNode(man)); } if (man is XamlIlManipulationGroupNode grp) { ProcessDirectiveCandidateList(grp.Children); } if (man is XamlIlObjectInitializationNode init) { init.Manipulation = VisitManipulationNode(init.Manipulation); } return(man); } if (value is XamlIlAstObjectNode astObject) { ProcessDirectiveCandidateList(astObject.Children); } else if (value is XamlIlValueWithManipulationNode vman) { vman.Manipulation = VisitManipulationNode(vman.Manipulation); } var adder = FindAdder(vtype, keyNode?.Type.GetClrType()); if (adder != null) { var args = new List <IXamlIlAstValueNode>(); if (keyNode != null) { args.Add(keyNode); } args.Add(value); rv = new XamlIlNoReturnMethodCallNode(value, adder, args); if (targetProperty != null) { rv = new XamlIlPropertyValueManipulationNode(value, targetProperty, rv); } return(true); } } return(false); }
public override void VisitChildren(XamlIlAstVisitorDelegate visitor) { Manipulation = (IXamlIlAstManipulationNode)Manipulation.Visit(visitor); }
public override void VisitChildren(XamlIlAstVisitorDelegate visitor) { Value = (IXamlIlAstValueNode)Value?.Visit(visitor); Manipulation = (IXamlIlAstManipulationNode)Manipulation?.Visit(visitor); }
public override void VisitChildren(Visitor visitor) { base.VisitChildren(visitor); Manipulation = (IXamlIlAstManipulationNode)Manipulation?.Visit(visitor); }
public override void VisitChildren(Visitor visitor) { Value = (XamlIlAstCompilerLocalNode)Value.Visit(visitor); Manipulation = (IXamlIlAstManipulationNode)Manipulation.Visit(visitor); }
public XamlIlAstImperativeValueManipulation(IXamlIlLineInfo lineInfo, IXamlIlAstValueNode value, IXamlIlAstManipulationNode manipulation) : base(lineInfo) { Value = value; Manipulation = manipulation; }