public static TagHelperDescriptorBuilder BoundAttributeDescriptor( this TagHelperDescriptorBuilder builder, Action <BoundAttributeDescriptorBuilder> configure) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.BindAttribute(configure); return(builder); }
private void CreateTypeParameterProperty(TagHelperDescriptorBuilder builder, ITypeParameterSymbol typeParameter, bool cascade) { builder.BindAttribute(pb => { pb.DisplayName = typeParameter.Name; pb.Name = typeParameter.Name; pb.TypeName = typeof(Type).FullName; pb.SetPropertyName(typeParameter.Name); pb.Metadata[ComponentMetadata.Component.TypeParameterKey] = bool.TrueString; pb.Metadata[ComponentMetadata.Component.TypeParameterIsCascadingKey] = cascade.ToString(); // Type constraints (like "Image" or "Foo") are stored indepenently of // things like constructor constraints and not null constraints in the // type parameter so we create a single string representation of all the constraints // here. var constraintString = new StringBuilder(); if (typeParameter.ConstraintTypes.Any()) { constraintString.Append(string.Join(", ", typeParameter.ConstraintTypes.Select(t => t.Name))); } if (typeParameter.HasConstructorConstraint) { constraintString.Append(", new()"); } if (typeParameter.HasNotNullConstraint) { constraintString.Append(", notnull"); } if (typeParameter.HasReferenceTypeConstraint) { constraintString.Append(", class"); } if (typeParameter.HasUnmanagedTypeConstraint) { constraintString.Append(", unmanaged"); } if (typeParameter.HasValueTypeConstraint) { constraintString.Append(", struct"); } if (constraintString.Length > 0) { constraintString.Insert(0, "where " + typeParameter.Name + " : "); pb.Metadata[ComponentMetadata.Component.TypeParameterConstraintsKey] = constraintString.ToString(); } pb.Documentation = string.Format(CultureInfo.InvariantCulture, ComponentResources.ComponentTypeParameter_Documentation, typeParameter.Name, builder.Name); }); }
private void CreateTypeParameterProperty(TagHelperDescriptorBuilder builder, ITypeSymbol typeParameter) { builder.BindAttribute(pb => { pb.DisplayName = typeParameter.Name; pb.Name = typeParameter.Name; pb.TypeName = typeof(Type).FullName; pb.SetPropertyName(typeParameter.Name); pb.Metadata[BlazorMetadata.Component.TypeParameterKey] = bool.TrueString; pb.Documentation = string.Format(Resources.ComponentTypeParameter_Documentation, typeParameter.Name, builder.Name); }); }
private void CreateTypeParameterProperty(TagHelperDescriptorBuilder builder, ITypeSymbol typeParameter, bool cascade) { builder.BindAttribute(pb => { pb.DisplayName = typeParameter.Name; pb.Name = typeParameter.Name; pb.TypeName = typeof(Type).FullName; pb.SetPropertyName(typeParameter.Name); pb.Metadata[ComponentMetadata.Component.TypeParameterKey] = bool.TrueString; pb.Metadata[ComponentMetadata.Component.TypeParameterIsCascadingKey] = cascade.ToString(); pb.Documentation = string.Format(CultureInfo.InvariantCulture, ComponentResources.ComponentTypeParameter_Documentation, typeParameter.Name, builder.Name); }); }
private void AddBoundAttributes(INamedTypeSymbol type, TagHelperDescriptorBuilder builder) { var accessibleProperties = GetAccessibleProperties(type); foreach (var property in accessibleProperties) { if (ShouldSkipDescriptorCreation(property)) { continue; } builder.BindAttribute(attributeBuilder => { ConfigureBoundAttribute(attributeBuilder, property, type); }); } }
private void CreateContextParameter(TagHelperDescriptorBuilder builder, string childContentName) { builder.BindAttribute(b => { b.Name = ComponentMetadata.ChildContent.ParameterAttributeName; b.TypeName = typeof(string).FullName; b.Metadata.Add(ComponentMetadata.Component.ChildContentParameterNameKey, bool.TrueString); if (childContentName == null) { b.Documentation = ComponentResources.ChildContentParameterName_TopLevelDocumentation; } else { b.Documentation = string.Format(ComponentResources.ChildContentParameterName_Documentation, childContentName); } }); }
private void CreateProperty(TagHelperDescriptorBuilder builder, IPropertySymbol property, PropertyKind kind) { builder.BindAttribute(pb => { pb.Name = property.Name; pb.TypeName = property.Type.ToDisplayString(FullNameTypeDisplayFormat); pb.SetPropertyName(property.Name); if (kind == PropertyKind.Enum) { pb.IsEnum = true; } if (kind == PropertyKind.ChildContent) { pb.Metadata.Add(BlazorMetadata.Component.ChildContentKey, bool.TrueString); } if (kind == PropertyKind.Delegate) { pb.Metadata.Add(BlazorMetadata.Component.DelegateSignatureKey, bool.TrueString); } if (HasTypeParameter(property.Type)) { pb.Metadata.Add(BlazorMetadata.Component.GenericTypedKey, bool.TrueString); } var xml = property.GetDocumentationCommentXml(); if (!string.IsNullOrEmpty(xml)) { pb.Documentation = xml; } }); bool HasTypeParameter(ITypeSymbol type) { if (type is ITypeParameterSymbol) { return(true); } // We need to check for cases like: // [Parameter] List<T> MyProperty { get; set; } // AND // [Parameter] List<string> MyProperty { get; set; } // // We need to inspect the type arguments to tell the difference between a property that // uses the containing class' type parameter(s) and a vanilla usage of generic types like // List<> and Dictionary<,> // // Since we need to handle cases like RenderFragment<List<T>>, this check must be recursive. if (type is INamedTypeSymbol namedType && namedType.IsGenericType) { var typeArguments = namedType.TypeArguments; for (var i = 0; i < typeArguments.Length; i++) { if (HasTypeParameter(typeArguments[i])) { return(true); } } // Another case to handle - if the type being inspected is a nested type // inside a generic containing class. The common usage for this would be a case // where a generic templated component defines a 'context' nested class. if (namedType.ContainingType != null && HasTypeParameter(namedType.ContainingType)) { return(true); } } return(false); } }
private static void ReadBoundAttribute(JsonReader reader, TagHelperDescriptorBuilder builder) { if (!reader.Read()) { return; } if (reader.TokenType != JsonToken.StartObject) { return; } builder.BindAttribute(attribute => { reader.ReadProperties(propertyName => { switch (propertyName) { case nameof(BoundAttributeDescriptor.Name): if (reader.Read()) { var name = (string)reader.Value; attribute.Name = name; } break; case nameof(BoundAttributeDescriptor.TypeName): if (reader.Read()) { var typeName = (string)reader.Value; attribute.TypeName = typeName; } break; case nameof(BoundAttributeDescriptor.Documentation): if (reader.Read()) { var documentation = (string)reader.Value; attribute.Documentation = documentation; } break; case nameof(BoundAttributeDescriptor.IndexerNamePrefix): if (reader.Read()) { var indexerNamePrefix = (string)reader.Value; if (indexerNamePrefix != null) { attribute.IsDictionary = true; attribute.IndexerAttributeNamePrefix = indexerNamePrefix; } } break; case nameof(BoundAttributeDescriptor.IndexerTypeName): if (reader.Read()) { var indexerTypeName = (string)reader.Value; if (indexerTypeName != null) { attribute.IsDictionary = true; attribute.IndexerValueTypeName = indexerTypeName; } } break; case nameof(BoundAttributeDescriptor.IsEnum): if (reader.Read()) { var isEnum = (bool)reader.Value; attribute.IsEnum = isEnum; } break; case nameof(BoundAttributeDescriptor.BoundAttributeParameters): ReadBoundAttributeParameters(reader, attribute); break; case nameof(BoundAttributeDescriptor.Diagnostics): ReadDiagnostics(reader, attribute.Diagnostics); break; case nameof(BoundAttributeDescriptor.Metadata): ReadMetadata(reader, attribute.Metadata); break; } }); }); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.StartObject) { return(null); } JObject jObject = JObject.Load(reader); string kind = jObject["Kind"].Value <string>(); string name = jObject["Name"].Value <string>(); string assemblyName = jObject["AssemblyName"].Value <string>(); JArray jArray = jObject["TagMatchingRules"].Value <JArray>(); JArray jArray2 = jObject["BoundAttributes"].Value <JArray>(); JArray jArray3 = jObject["AllowedChildTags"].Value <JArray>(); string documentation = jObject["Documentation"].Value <string>(); string tagOutputHint = jObject["TagOutputHint"].Value <string>(); bool caseSensitive = jObject["CaseSensitive"].Value <bool>(); JArray jArray4 = jObject["Diagnostics"].Value <JArray>(); JObject jObject2 = jObject["Metadata"].Value <JObject>(); TagHelperDescriptorBuilder tagHelperDescriptorBuilder = TagHelperDescriptorBuilder.Create(kind, name, assemblyName); tagHelperDescriptorBuilder.Documentation = documentation; tagHelperDescriptorBuilder.TagOutputHint = tagOutputHint; tagHelperDescriptorBuilder.CaseSensitive = caseSensitive; foreach (JToken item2 in jArray) { JObject rule = item2.Value <JObject>(); tagHelperDescriptorBuilder.TagMatchingRule(delegate(TagMatchingRuleDescriptorBuilder b) { ReadTagMatchingRule(b, rule, serializer); }); } foreach (JToken item3 in jArray2) { JObject attribute = item3.Value <JObject>(); tagHelperDescriptorBuilder.BindAttribute(delegate(BoundAttributeDescriptorBuilder b) { ReadBoundAttribute(b, attribute, serializer); }); } foreach (JToken item4 in jArray3) { JObject tag = item4.Value <JObject>(); tagHelperDescriptorBuilder.AllowChildTag(delegate(AllowedChildTagDescriptorBuilder childTagBuilder) { ReadAllowedChildTag(childTagBuilder, tag, serializer); }); } foreach (JToken item5 in jArray4) { JsonReader reader2 = item5.CreateReader(); RazorDiagnostic item = serializer.Deserialize <RazorDiagnostic>(reader2); tagHelperDescriptorBuilder.Diagnostics.Add(item); } JsonReader reader3 = jObject2.CreateReader(); foreach (KeyValuePair <string, string> item6 in serializer.Deserialize <Dictionary <string, string> >(reader3)) { tagHelperDescriptorBuilder.Metadata[item6.Key] = item6.Value; } return(tagHelperDescriptorBuilder.Build()); }