Re-enable the model keyword for Mvc Razor.

This commit is contained in:
N. Taylor Mullen 2014-02-03 15:15:42 -08:00
parent 3d6740bc8a
commit 226d632794
3 changed files with 139 additions and 0 deletions

View File

@ -0,0 +1,32 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.CodeDom;
using Microsoft.AspNet.Razor;
using Microsoft.AspNet.Razor.Generator;
namespace Microsoft.AspNet.Mvc.Razor
{
internal class MvcRazorCodeGenerator : CSharpRazorCodeGenerator
{
private const string DefaultModelTypeName = "dynamic";
public MvcRazorCodeGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host)
: base(className, rootNamespaceName, sourceFileName, host)
{
var mvcHost = host as MvcRazorHost;
if (mvcHost != null)
{
// set the default model type to "dynamic" (Dev10 bug 935656)
// don't set it for "special" pages (such as "_viewStart.cshtml")
SetBaseType(DefaultModelTypeName);
}
}
private void SetBaseType(string modelTypeName)
{
var baseType = new CodeTypeReference(Context.Host.DefaultBaseClass + "<" + modelTypeName + ">");
Context.GeneratedClass.BaseTypes.Clear();
Context.GeneratedClass.BaseTypes.Add(baseType);
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Globalization;
using Microsoft.AspNet.Razor.Generator;
using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.Text;
namespace Microsoft.AspNet.Mvc.Razor
{
public class MvcRazorCodeParser : CSharpCodeParser
{
private const string ModelKeyword = "model";
private const string GenericTypeFormatString = "{0}<{1}>";
private SourceLocation? _endInheritsLocation;
private bool _modelStatementFound;
public MvcRazorCodeParser()
{
MapDirectives(ModelDirective, ModelKeyword);
}
protected override void InheritsDirective()
{
// Verify we're on the right keyword and accept
AssertDirective(SyntaxConstants.CSharp.InheritsKeyword);
AcceptAndMoveNext();
_endInheritsLocation = CurrentLocation;
InheritsDirectiveCore();
CheckForInheritsAndModelStatements();
}
private void CheckForInheritsAndModelStatements()
{
if (_modelStatementFound && _endInheritsLocation.HasValue)
{
Context.OnError(_endInheritsLocation.Value, String.Format(CultureInfo.CurrentCulture, "MvcResources.MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword", ModelKeyword));
}
}
protected virtual void ModelDirective()
{
// Verify we're on the right keyword and accept
AssertDirective(ModelKeyword);
AcceptAndMoveNext();
SourceLocation endModelLocation = CurrentLocation;
BaseTypeDirective(
String.Format(CultureInfo.CurrentCulture,
"MvcResources.MvcRazorCodeParser_ModelKeywordMustBeFollowedByTypeName", ModelKeyword),
CreateModelCodeGenerator);
if (_modelStatementFound)
{
Context.OnError(endModelLocation, String.Format(CultureInfo.CurrentCulture, "MvcResources.MvcRazorCodeParser_OnlyOneModelStatementIsAllowed", ModelKeyword));
}
_modelStatementFound = true;
CheckForInheritsAndModelStatements();
}
private SpanCodeGenerator CreateModelCodeGenerator(string model)
{
return new SetModelTypeCodeGenerator(model, GenericTypeFormatString);
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Globalization;
using Microsoft.AspNet.Razor.Generator;
namespace Microsoft.AspNet.Mvc.Razor
{
internal class SetModelTypeCodeGenerator : SetBaseTypeCodeGenerator
{
private string _genericTypeFormat;
public SetModelTypeCodeGenerator(string modelType, string genericTypeFormat)
: base(modelType)
{
_genericTypeFormat = genericTypeFormat;
}
protected override string ResolveType(CodeGeneratorContext context, string baseType)
{
return String.Format(
CultureInfo.InvariantCulture,
_genericTypeFormat,
context.Host.DefaultBaseClass,
baseType);
}
public override bool Equals(object obj)
{
SetModelTypeCodeGenerator other = obj as SetModelTypeCodeGenerator;
return other != null &&
base.Equals(obj) &&
String.Equals(_genericTypeFormat, other._genericTypeFormat, StringComparison.Ordinal);
}
public override string ToString()
{
return "Model:" + BaseType;
}
}
}