Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/aspnetcore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMackinnon Buck <mackinnon.buck@gmail.com>2021-09-03 03:53:09 +0300
committerMackinnon Buck <mackinnon.buck@gmail.com>2021-09-03 03:53:09 +0300
commit506322c5726000fc543e1786868a38044cd385a3 (patch)
tree747ad306f5759acf0aed346174b6f0df507f60a2
parent848cdb37a63285462d10890255ae3034f3db461c (diff)
Improved design for inherited parameterst-mbuck/code-gen-component-parameters
-rw-r--r--src/Components/Components/src/ComponentBase.cs13
-rw-r--r--src/Components/Components/src/ParameterView.cs15
-rw-r--r--src/Components/Components/src/PublicAPI.Unshipped.txt3
-rw-r--r--src/Components/Components/src/Reflection/ComponentProperties.cs88
-rw-r--r--src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs7
-rw-r--r--src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs37
-rw-r--r--src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPropertySetterProviderPass.cs2
-rw-r--r--src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs114
-rw-r--r--src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/TestComponent.mappings.txt2
-rw-r--r--src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components.netstandard2.0.cs4
10 files changed, 165 insertions, 120 deletions
diff --git a/src/Components/Components/src/ComponentBase.cs b/src/Components/Components/src/ComponentBase.cs
index d9dd102bf8..65db35c444 100644
--- a/src/Components/Components/src/ComponentBase.cs
+++ b/src/Components/Components/src/ComponentBase.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components
@@ -19,7 +20,7 @@ namespace Microsoft.AspNetCore.Components
/// Optional base class for components. Alternatively, components may
/// implement <see cref="IComponent"/> directly.
/// </summary>
- public abstract class ComponentBase : IComponent, IHandleEvent, IHandleAfterRender
+ public abstract class ComponentBase : IComponent, IHandleEvent, IHandleAfterRender, IPropertySetterProvider
{
private readonly RenderFragment _renderFragment;
private RenderHandle _renderHandle;
@@ -28,6 +29,9 @@ namespace Microsoft.AspNetCore.Components
private bool _hasPendingQueuedRender;
private bool _hasCalledOnAfterRender;
+ /// <inheritdoc/>
+ public virtual IUnmatchedValuesPropertySetter? UnmatchedValuesPropertySetter => default;
+
/// <summary>
/// Constructs an instance of <see cref="ComponentBase"/>.
/// </summary>
@@ -221,6 +225,13 @@ namespace Microsoft.AspNetCore.Components
}
}
+ /// <inheritdoc/>
+ public virtual bool TryGetSetter(string propertyName, [NotNullWhen(true)] out IPropertySetter? propertySetter)
+ {
+ propertySetter = default;
+ return false;
+ }
+
private async Task RunInitAndSetParametersAsync()
{
OnInitialized();
diff --git a/src/Components/Components/src/ParameterView.cs b/src/Components/Components/src/ParameterView.cs
index ae3fe17fcf..6eb97f0685 100644
--- a/src/Components/Components/src/ParameterView.cs
+++ b/src/Components/Components/src/ParameterView.cs
@@ -260,6 +260,21 @@ namespace Microsoft.AspNetCore.Components
}
/// <summary>
+ /// For each parameter property on <paramref name="target"/>, updates its value to
+ /// match the corresponding entry in the <see cref="ParameterView"/>.
+ /// </summary>
+ /// <param name="target">An object that has a public writable property matching each parameter's name and type.</param>
+ public void SetParameterProperties(IPropertySetterProvider target)
+ {
+ if (target is null)
+ {
+ throw new ArgumentNullException(nameof(target));
+ }
+
+ ComponentProperties.SetProperties(this, target);
+ }
+
+ /// <summary>
/// An enumerator that iterates through a <see cref="ParameterView"/>.
/// </summary>
diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt
index aa95835c55..7ccbe039f2 100644
--- a/src/Components/Components/src/PublicAPI.Unshipped.txt
+++ b/src/Components/Components/src/PublicAPI.Unshipped.txt
@@ -40,6 +40,7 @@ Microsoft.AspNetCore.Components.NavigationOptions.ForceLoad.init -> void
Microsoft.AspNetCore.Components.NavigationOptions.NavigationOptions() -> void
Microsoft.AspNetCore.Components.NavigationOptions.ReplaceHistoryEntry.get -> bool
Microsoft.AspNetCore.Components.NavigationOptions.ReplaceHistoryEntry.init -> void
+Microsoft.AspNetCore.Components.ParameterView.SetParameterProperties(Microsoft.AspNetCore.Components.IPropertySetterProvider! target) -> void
Microsoft.AspNetCore.Components.RenderHandle.IsRenderingOnMetadataUpdate.get -> bool
Microsoft.AspNetCore.Components.RenderTree.Renderer.RemoveRootComponent(int componentId) -> void
Microsoft.AspNetCore.Components.IPersistentComponentStateStore
@@ -127,6 +128,8 @@ static Microsoft.AspNetCore.Components.NavigationManagerExtensions.GetUriWithQue
static Microsoft.AspNetCore.Components.NavigationManagerExtensions.GetUriWithQueryParameters(this Microsoft.AspNetCore.Components.NavigationManager! navigationManager, System.Collections.Generic.IReadOnlyDictionary<string!, object?>! parameters) -> string!
static Microsoft.AspNetCore.Components.NavigationManagerExtensions.GetUriWithQueryParameters(this Microsoft.AspNetCore.Components.NavigationManager! navigationManager, string! uri, System.Collections.Generic.IReadOnlyDictionary<string!, object?>! parameters) -> string!
static Microsoft.AspNetCore.Components.ParameterView.FromDictionary(System.Collections.Generic.IDictionary<string!, object?>! parameters) -> Microsoft.AspNetCore.Components.ParameterView
+virtual Microsoft.AspNetCore.Components.ComponentBase.TryGetSetter(string! propertyName, out Microsoft.AspNetCore.Components.IPropertySetter? propertySetter) -> bool
+virtual Microsoft.AspNetCore.Components.ComponentBase.UnmatchedValuesPropertySetter.get -> Microsoft.AspNetCore.Components.IUnmatchedValuesPropertySetter?
virtual Microsoft.AspNetCore.Components.NavigationManager.NavigateToCore(string! uri, Microsoft.AspNetCore.Components.NavigationOptions options) -> void
virtual Microsoft.AspNetCore.Components.NavigationManager.NavigateToCore(string! uri, bool forceLoad) -> void
virtual Microsoft.AspNetCore.Components.RenderTree.Renderer.DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo? fieldInfo, System.EventArgs! eventArgs) -> System.Threading.Tasks.Task!
diff --git a/src/Components/Components/src/Reflection/ComponentProperties.cs b/src/Components/Components/src/Reflection/ComponentProperties.cs
index 1fcc915ab2..7ac15057b2 100644
--- a/src/Components/Components/src/Reflection/ComponentProperties.cs
+++ b/src/Components/Components/src/Reflection/ComponentProperties.cs
@@ -26,19 +26,27 @@ namespace Microsoft.AspNetCore.Components.Reflection
throw new ArgumentNullException(nameof(target));
}
- var targetType = target.GetType();
+ var writers = GetWritersForType(target.GetType());
+ SetProperties(parameters, writers, target);
+ }
- if (target is not IPropertySetterProvider propertySetterProvider)
+ public static void SetProperties(in ParameterView parameters, IPropertySetterProvider target)
+ {
+ if (target == null)
{
- if (!_cachedWritersByType.TryGetValue(targetType, out var writers))
- {
- writers = new WritersForType(targetType);
- _cachedWritersByType[targetType] = writers;
- }
-
- propertySetterProvider = writers;
+ throw new ArgumentNullException(nameof(target));
}
+ var provider = new FallbackPropertySetterProvider(target);
+ SetProperties(parameters, provider, target);
+ }
+
+ private static void SetProperties<TProvider>(
+ in ParameterView parameters,
+ in TProvider propertySetterProvider,
+ object target) where TProvider : IPropertySetterProvider
+ {
+ var targetType = target.GetType();
var unmatchedValuesSetter = propertySetterProvider.UnmatchedValuesPropertySetter;
// The logic is split up for simplicity now that we have CaptureUnmatchedValues parameters.
@@ -48,13 +56,13 @@ namespace Microsoft.AspNetCore.Components.Reflection
foreach (var parameter in parameters)
{
var parameterName = parameter.Name;
- if (!propertySetterProvider.TryGetSetter(parameterName, out var writer))
+ if (!propertySetterProvider.TryGetSetter(parameterName, out var setter))
{
// Case 1: There is nowhere to put this value.
ThrowForUnknownIncomingParameterName(targetType, parameterName);
throw null; // Unreachable
}
- else if (writer.Cascading && !parameter.Cascading)
+ else if (setter.Cascading && !parameter.Cascading)
{
// We don't allow you to set a cascading parameter with a non-cascading value. Put another way:
// cascading parameters are not part of the public API of a component, so it's not reasonable
@@ -65,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
ThrowForSettingCascadingParameterWithNonCascadingValue(targetType, parameterName);
throw null; // Unreachable
}
- else if (!writer.Cascading && parameter.Cascading)
+ else if (!setter.Cascading && parameter.Cascading)
{
// We're giving a more specific error here because trying to set a non-cascading parameter
// with a cascading value is likely deliberate (but not supported), or is a bug in our code.
@@ -73,7 +81,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
throw null; // Unreachable
}
- SetProperty(target, writer, parameterName, parameter.Value);
+ SetProperty(target, setter, parameterName, parameter.Value);
}
}
else
@@ -89,9 +97,9 @@ namespace Microsoft.AspNetCore.Components.Reflection
isCaptureUnmatchedValuesParameterSetExplicitly = true;
}
- if (propertySetterProvider.TryGetSetter(parameterName, out var writer))
+ if (propertySetterProvider.TryGetSetter(parameterName, out var setter))
{
- if (!writer.Cascading && parameter.Cascading)
+ if (!setter.Cascading && parameter.Cascading)
{
// Don't allow an "extra" cascading value to be collected - or don't allow a non-cascading
// parameter to be set with a cascading value.
@@ -100,7 +108,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
ThrowForSettingParameterWithCascadingValue(targetType, parameterName);
throw null; // Unreachable
}
- else if (writer.Cascading && !parameter.Cascading)
+ else if (setter.Cascading && !parameter.Cascading)
{
// Allow unmatched parameters to collide with the names of cascading parameters. This is
// valid because cascading parameter names are not part of the public API. There's no
@@ -111,7 +119,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
}
else
{
- SetProperty(target, writer, parameterName, parameter.Value);
+ SetProperty(target, setter, parameterName, parameter.Value);
}
}
else
@@ -166,6 +174,42 @@ namespace Microsoft.AspNetCore.Components.Reflection
}
}
+ // This struct wraps the provided IPropertySetterProvider, using a fallback, reflection-based
+ // IPropertySetterProvider when the target cannot provide a property.
+ private struct FallbackPropertySetterProvider : IPropertySetterProvider
+ {
+ private readonly IPropertySetterProvider _target;
+ private IPropertySetterProvider? _fallback;
+
+ private IPropertySetterProvider Fallback
+ => _fallback ??= GetWritersForType(_target.GetType());
+
+ public FallbackPropertySetterProvider(IPropertySetterProvider target)
+ {
+ _target = target;
+ _fallback = default;
+ }
+
+ public IUnmatchedValuesPropertySetter? UnmatchedValuesPropertySetter
+ => _target.UnmatchedValuesPropertySetter
+ ?? Fallback.UnmatchedValuesPropertySetter;
+
+ public bool TryGetSetter(string propertyName, [NotNullWhen(true)] out IPropertySetter? propertySetter)
+ => _target.TryGetSetter(propertyName, out propertySetter)
+ || Fallback.TryGetSetter(propertyName, out propertySetter);
+ }
+
+ private static WritersForType GetWritersForType(Type targetType)
+ {
+ if (!_cachedWritersByType.TryGetValue(targetType, out var writers))
+ {
+ writers = new WritersForType(targetType);
+ _cachedWritersByType[targetType] = writers;
+ }
+
+ return writers;
+ }
+
internal static IEnumerable<PropertyInfo> GetCandidateBindableProperties([DynamicallyAccessedMembers(Component)] Type targetType)
=> MemberAssignment.GetPropertiesIncludingInherited(targetType, BindablePropertyFlags);
@@ -319,7 +363,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
}
}
- public bool TryGetSetter(string parameterName, [MaybeNullWhen(false)] out IPropertySetter writer)
+ public bool TryGetSetter(string parameterName, [MaybeNullWhen(false)] out IPropertySetter setter)
{
// In intensive parameter-passing scenarios, one of the most expensive things we do is the
// lookup from parameterName to writer. Pre-5.0 that was because of the string hashing.
@@ -328,9 +372,9 @@ namespace Microsoft.AspNetCore.Components.Reflection
// having to hash the string. We only fall back on hashing the string if the cache gets full,
// which would only be in very unusual situations because components don't typically have many
// parameters, and the parameterName strings usually come from compile-time constants.
- if (!_referenceEqualityWritersCache.TryGetValue(parameterName, out writer))
+ if (!_referenceEqualityWritersCache.TryGetValue(parameterName, out setter))
{
- _underlyingWriters.TryGetValue(parameterName, out writer);
+ _underlyingWriters.TryGetValue(parameterName, out setter);
// Note that because we're not locking around this, it's possible we might
// actually write more than MaxCachedWriterLookups entries due to concurrent
@@ -341,11 +385,11 @@ namespace Microsoft.AspNetCore.Components.Reflection
// being passed as catch-all parameter values.
if (_referenceEqualityWritersCache.Count < MaxCachedWriterLookups)
{
- _referenceEqualityWritersCache.TryAdd(parameterName, writer);
+ _referenceEqualityWritersCache.TryAdd(parameterName, setter);
}
}
- return writer != null;
+ return setter != null;
}
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
index 5215d3b35b..0da1c22cc3 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
@@ -804,13 +804,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
}
}
- public override void WriteComponentParameterData(CodeRenderingContext context, ComponentParameterDataIntermediateNode node)
- {
- WriteUnmatchedValuesPropertySetterProperty(context);
- WriteTryGetSetterSignature(context);
- WriteTryGetSetterDefaultBody(context);
- }
-
public override void WriteTemplate(CodeRenderingContext context, TemplateIntermediateNode node)
{
if (context == null)
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
index d3ca5fa4f4..e5f4dd340e 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
@@ -273,43 +273,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
}
}
- protected static void WriteUnmatchedValuesPropertySetterProperty(CodeRenderingContext context)
- {
- context.CodeWriter.Write(ComponentsApi.IUnmatchedValuesPropertySetter.FullTypeName);
- context.CodeWriter.Write(" ");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.FullTypeName);
- context.CodeWriter.Write(".");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.UnmatchedValuesPropertySetter);
- context.CodeWriter.WriteLine(" { get; }");
- }
-
- protected static void WriteTryGetSetterSignature(CodeRenderingContext context)
- {
- context.CodeWriter.Write("bool ");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.FullTypeName);
- context.CodeWriter.Write(".");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.TryGetSetter);
- context.CodeWriter.Write("(");
- context.CodeWriter.Write("string ");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertyNameParameter);
- context.CodeWriter.Write(", ");
- context.CodeWriter.Write("out ");
- context.CodeWriter.Write(ComponentsApi.IPropertySetter.FullTypeName);
- context.CodeWriter.Write(" ");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySetterParameter);
- context.CodeWriter.WriteLine(")");
- }
-
- protected static void WriteTryGetSetterDefaultBody(CodeRenderingContext context)
- {
- using (context.CodeWriter.BuildScope())
- {
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySetterParameter);
- context.CodeWriter.WriteLine(" = default;");
- context.CodeWriter.WriteLine("return false;");
- }
- }
-
protected List<TypeInferenceMethodParameter> GetTypeInferenceMethodParameters(ComponentTypeInferenceMethodIntermediateNode node)
{
var p = new List<TypeInferenceMethodParameter>();
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPropertySetterProviderPass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPropertySetterProviderPass.cs
index 8e96aa960d..48afd4ce1c 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPropertySetterProviderPass.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPropertySetterProviderPass.cs
@@ -26,8 +26,6 @@ internal class ComponentPropertySetterProviderPass : ComponentIntermediateNodePa
BuildComponentParameterData(codeDocument.GetTagHelperContext(), componentParameterDataNode);
- primaryClass.Interfaces.Add(ComponentsApi.IPropertySetterProvider.FullTypeName);
-
var nodeParameterDataBuilder = IntermediateNodeBuilder.Create(primaryClass);
nodeParameterDataBuilder.Add(componentParameterDataNode);
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
index 2d52b00052..941dd97b56 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
@@ -742,62 +742,78 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// 2. Handle properties capturing unmatched values.
// 3. Utilize existing CodeWriter extensions where possible.
- var hasParameters = node.ParameterData.Count > 0;
-
- if (hasParameters)
+ if (node.ParameterData.Count == 0)
{
- // Writes something like:
- // private static readonly Lazy<Dictionary<string, DelegatePropertySetter<MyComponent>>> __propertyWriters = new(static () => new()
- // {
- // [nameof(Param1)] = new(static (c, v) => c.Param1 = (bool)value),
- // ...
- // });
- context.CodeWriter.Write("private static readonly Lazy<Dictionary<string, ");
+ return;
+ }
+
+ // Writes something like:
+ //
+ // private static readonly Lazy<Dictionary<string, IPropertySetter>> __propertyWriters = new(static () => new()
+ // {
+ // [nameof(Param1)] = new DelegatePropertySetter<MyComponent>(static (c, v) => c.Param1 = (bool)value),
+ // ...
+ // });
+ context.CodeWriter.Write("private static readonly Lazy<Dictionary<string, ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetter.FullTypeName);
+ context.CodeWriter.Write(">> ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySettersField);
+ context.CodeWriter.WriteLine("= new(static () => new()");
+ context.CodeWriter.WriteLine("{");
+ context.CodeWriter.CurrentIndent += context.CodeWriter.TabSize;
+
+ foreach (var parameterData in node.ParameterData)
+ {
+ context.CodeWriter.Write("[nameof(");
+ context.CodeWriter.Write(parameterData.Name);
+ context.CodeWriter.Write(")] = new ");
context.CodeWriter.Write(ComponentsApi.DelegatePropertySetter.FullTypeName);
context.CodeWriter.Write("<");
context.CodeWriter.Write(node.ComponentFullTypeName);
- context.CodeWriter.Write(">>> ");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySettersField);
- context.CodeWriter.WriteLine("= new(static () => new()");
- context.CodeWriter.WriteLine("{");
- context.CodeWriter.CurrentIndent += context.CodeWriter.TabSize;
-
- foreach (var parameterData in node.ParameterData)
- {
- context.CodeWriter.Write("[nameof(");
- context.CodeWriter.Write(parameterData.Name);
- context.CodeWriter.Write(")] = new(static (c, value) => c.");
- context.CodeWriter.Write(parameterData.Name);
- context.CodeWriter.Write(" = (");
- context.CodeWriter.Write(parameterData.TypeName);
- context.CodeWriter.WriteLine(")value),");
- }
-
- context.CodeWriter.CurrentIndent -= context.CodeWriter.TabSize;
- context.CodeWriter.WriteLine("});");
+ context.CodeWriter.Write(">");
+ context.CodeWriter.Write("(static (c, v) => c.");
+ context.CodeWriter.Write(parameterData.Name);
+ context.CodeWriter.Write(" = (");
+ context.CodeWriter.Write(parameterData.TypeName);
+ context.CodeWriter.WriteLine(")v),");
}
- WriteUnmatchedValuesPropertySetterProperty(context);
- WriteTryGetSetterSignature(context);
+ context.CodeWriter.CurrentIndent -= context.CodeWriter.TabSize;
+ context.CodeWriter.WriteLine("});");
- using (context.CodeWriter.BuildScope())
- {
- if (hasParameters)
- {
- context.CodeWriter.Write("var success = ");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySettersField);
- context.CodeWriter.Write(".Value.TryGetValue(");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertyNameParameter);
- context.CodeWriter.WriteLine(", out var result);");
- context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySetterParameter);
- context.CodeWriter.WriteLine(" = result;");
- context.CodeWriter.WriteLine("return success;");
- }
- else
- {
- WriteTryGetSetterDefaultBody(context);
- }
- }
+ // Writes something like:
+ //
+ // public override bool TryGetSetter(string propertyName, out IPropertySetter propertySetter)
+ // => __propertySetters.Value.TryGetValue(propertyName, out propertySetter)
+ // || base.TryGetSetter(propertyName, out propertySetter);
+ context.CodeWriter.Write("public override bool ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.TryGetSetter);
+ context.CodeWriter.Write("(");
+ context.CodeWriter.Write("string ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertyNameParameter);
+ context.CodeWriter.Write(", ");
+ context.CodeWriter.Write("out ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetter.FullTypeName);
+ context.CodeWriter.Write(" ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySetterParameter);
+ context.CodeWriter.WriteLine(")");
+
+ context.CodeWriter.CurrentIndent += context.CodeWriter.TabSize;
+ context.CodeWriter.Write("=> ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySettersField);
+ context.CodeWriter.Write(".Value.TryGetValue(");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertyNameParameter);
+ context.CodeWriter.Write(", out ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySetterParameter);
+ context.CodeWriter.WriteLine(")");
+ context.CodeWriter.Write("|| base.");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.TryGetSetter);
+ context.CodeWriter.Write("(");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertyNameParameter);
+ context.CodeWriter.Write(", out ");
+ context.CodeWriter.Write(ComponentsApi.IPropertySetterProvider.PropertySetterParameter);
+ context.CodeWriter.WriteLine(");");
+ context.CodeWriter.CurrentIndent -= context.CodeWriter.TabSize;
}
public override void WriteTemplate(CodeRenderingContext context, TemplateIntermediateNode node)
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/TestComponent.mappings.txt
index 76387ba727..896f8df0cc 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/TestComponent.mappings.txt
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/TestComponent.mappings.txt
@@ -21,7 +21,7 @@ Source Location: (294:15,7 [236] x:\dir\subdir\Test\TestComponent.cshtml)
[Parameter] public TItem3 Item3 { get; set; }
[Parameter] public RenderFragment<TItem2> ChildContent { get; set; }
|
-Generated Location: (1589:57,7 [236] )
+Generated Location: (2838:67,7 [236] )
|
[Parameter] public TItem1 Item1 { get; set; }
[Parameter] public List<TItem2> Items2 { get; set; }
diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components.netstandard2.0.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components.netstandard2.0.cs
index ce0218b941..e9f88e8fbe 100644
--- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components.netstandard2.0.cs
+++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components.netstandard2.0.cs
@@ -92,9 +92,11 @@ namespace Microsoft.AspNetCore.Components
public ChangeEventArgs() { }
public object Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
- public abstract partial class ComponentBase : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, Microsoft.AspNetCore.Components.IHandleEvent
+ public abstract partial class ComponentBase : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, Microsoft.AspNetCore.Components.IHandleEvent, Microsoft.AspNetCore.Components.IPropertySetterProvider
{
public ComponentBase() { }
+ public virtual IUnmatchedValuesPropertySetter UnmatchedValuesPropertySetter { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ public virtual bool TryGetSetter(string propertyName, out Microsoft.AspNetCore.Components.IPropertySetter propertySetter) { throw null; }
protected virtual void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected System.Threading.Tasks.Task InvokeAsync(System.Action workItem) { throw null; }
protected System.Threading.Tasks.Task InvokeAsync(System.Func<System.Threading.Tasks.Task> workItem) { throw null; }