Add ModelExpression code generation.
- Sealed the ModelExpression. - We use the stringified version of the ModelExpression type name to detect ModelExpression properties on TagHelpers. This is so the MvcRazorHost can work in tooling and in runtime. - Created a GeneratedTagHelperAttributeContext to represent the specific stringified versions of the ModelExpression assets. - Created an MvcTagHelperAttributeValueCodeRenderer to modify rendering of ModelExpression properties. #1241
This commit is contained in:
parent
ad76a3c8fb
commit
2005c3cd85
|
|
@ -10,7 +10,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes an <see cref="System.Linq.Expressions.Expression"/> passed to a tag helper.
|
/// Describes an <see cref="System.Linq.Expressions.Expression"/> passed to a tag helper.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ModelExpression
|
public sealed class ModelExpression
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ModelExpression"/> class.
|
/// Initializes a new instance of the <see cref="ModelExpression"/> class.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains information for the <see cref="ITagHelper"/> attribute code generation process.
|
||||||
|
/// </summary>
|
||||||
|
public class GeneratedTagHelperAttributeContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the model expression type.
|
||||||
|
/// </summary>
|
||||||
|
public string ModelExpressionTypeName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name the method to create <c>ModelExpression</c>s.
|
||||||
|
/// </summary>
|
||||||
|
public string CreateModelExpressionMethodName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,20 +11,34 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
public class MvcCSharpCodeBuilder : CSharpCodeBuilder
|
public class MvcCSharpCodeBuilder : CSharpCodeBuilder
|
||||||
{
|
{
|
||||||
|
private readonly GeneratedTagHelperAttributeContext _tagHelperAttributeContext;
|
||||||
private readonly string _defaultModel;
|
private readonly string _defaultModel;
|
||||||
private readonly string _activateAttribute;
|
private readonly string _activateAttribute;
|
||||||
|
|
||||||
public MvcCSharpCodeBuilder([NotNull] CodeBuilderContext context,
|
public MvcCSharpCodeBuilder([NotNull] CodeBuilderContext context,
|
||||||
[NotNull] string defaultModel,
|
[NotNull] string defaultModel,
|
||||||
[NotNull] string activateAttribute)
|
[NotNull] string activateAttribute,
|
||||||
|
[NotNull] GeneratedTagHelperAttributeContext tagHelperAttributeContext)
|
||||||
: base(context)
|
: base(context)
|
||||||
{
|
{
|
||||||
|
_tagHelperAttributeContext = tagHelperAttributeContext;
|
||||||
_defaultModel = defaultModel;
|
_defaultModel = defaultModel;
|
||||||
_activateAttribute = activateAttribute;
|
_activateAttribute = activateAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Model { get; set; }
|
private string Model { get; set; }
|
||||||
|
|
||||||
|
protected override CSharpCodeVisitor CreateCSharpCodeVisitor([NotNull] CSharpCodeWriter writer,
|
||||||
|
[NotNull] CodeBuilderContext context)
|
||||||
|
{
|
||||||
|
var csharpCodeVisitor = base.CreateCSharpCodeVisitor(writer, context);
|
||||||
|
|
||||||
|
csharpCodeVisitor.TagHelperRenderer.AttributeValueCodeRenderer =
|
||||||
|
new MvcTagHelperAttributeValueCodeRenderer(_tagHelperAttributeContext);
|
||||||
|
|
||||||
|
return csharpCodeVisitor;
|
||||||
|
}
|
||||||
|
|
||||||
protected override CSharpCodeWritingScope BuildClassDeclaration(CSharpCodeWriter writer)
|
protected override CSharpCodeWritingScope BuildClassDeclaration(CSharpCodeWriter writer)
|
||||||
{
|
{
|
||||||
// Grab the last model chunk so it gets intellisense.
|
// Grab the last model chunk so it gets intellisense.
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,22 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
get { return "Microsoft.AspNet.Mvc.ActivateAttribute"; }
|
get { return "Microsoft.AspNet.Mvc.ActivateAttribute"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type name used to represent <see cref="ITagHelper"/> model expression properties.
|
||||||
|
/// </summary>
|
||||||
|
public virtual string ModelExpressionType
|
||||||
|
{
|
||||||
|
get { return "Microsoft.AspNet.Mvc.Rendering.ModelExpression"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the method name used to create model expressions.
|
||||||
|
/// </summary>
|
||||||
|
public virtual string CreateModelExpressionMethod
|
||||||
|
{
|
||||||
|
get { return "CreateModelExpression"; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public GeneratorResults GenerateCode(string rootRelativePath, Stream inputStream)
|
public GeneratorResults GenerateCode(string rootRelativePath, Stream inputStream)
|
||||||
{
|
{
|
||||||
|
|
@ -173,7 +189,15 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
[NotNull] CodeBuilderContext context)
|
[NotNull] CodeBuilderContext context)
|
||||||
{
|
{
|
||||||
UpdateCodeBuilder(context);
|
UpdateCodeBuilder(context);
|
||||||
return new MvcCSharpCodeBuilder(context, DefaultModel, ActivateAttribute);
|
|
||||||
|
return new MvcCSharpCodeBuilder(context,
|
||||||
|
DefaultModel,
|
||||||
|
ActivateAttribute,
|
||||||
|
new GeneratedTagHelperAttributeContext
|
||||||
|
{
|
||||||
|
ModelExpressionTypeName = ModelExpressionType,
|
||||||
|
CreateModelExpressionMethodName = CreateModelExpressionMethod
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCodeBuilder(CodeGeneratorContext context)
|
private void UpdateCodeBuilder(CodeGeneratorContext context)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||||
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class MvcTagHelperAttributeValueCodeRenderer : TagHelperAttributeValueCodeRenderer
|
||||||
|
{
|
||||||
|
private const string ModelLambdaVariableName = "__model";
|
||||||
|
|
||||||
|
private readonly GeneratedTagHelperAttributeContext _context;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a new instance of <see cref="MvcTagHelperAttributeValueCodeRenderer"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">Contains code generation information for rendering attribute values.</param>
|
||||||
|
public MvcTagHelperAttributeValueCodeRenderer([NotNull] GeneratedTagHelperAttributeContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <remarks>If the attribute being rendered is of the type
|
||||||
|
/// <see cref="GeneratedTagHelperAttributeContext.ModelExpressionTypeName"/> then a model expression will be
|
||||||
|
/// created by calling into <see cref="GeneratedTagHelperAttributeContext.CreateModelExpressionMethodName"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public override void RenderAttributeValue([NotNull] TagHelperAttributeDescriptor attributeDescriptor,
|
||||||
|
[NotNull] CSharpCodeWriter writer,
|
||||||
|
[NotNull] CodeBuilderContext codeBuilderContext,
|
||||||
|
[NotNull] Action<CSharpCodeWriter> renderAttributeValue)
|
||||||
|
{
|
||||||
|
var propertyType = attributeDescriptor.PropertyInfo.PropertyType;
|
||||||
|
|
||||||
|
if (propertyType.FullName.Equals(_context.ModelExpressionTypeName, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
writer.WriteStartMethodInvocation(_context.CreateModelExpressionMethodName)
|
||||||
|
.Write(ModelLambdaVariableName)
|
||||||
|
.Write(" => ")
|
||||||
|
.Write(ModelLambdaVariableName)
|
||||||
|
.Write(".");
|
||||||
|
|
||||||
|
renderAttributeValue(writer);
|
||||||
|
|
||||||
|
writer.WriteEndMethodInvocation(endLine: false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.RenderAttributeValue(attributeDescriptor, writer, codeBuilderContext, renderAttributeValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue