Revert "Adding support for activating view properties"
This reverts commit 21bb8cb9fb.
This commit is contained in:
parent
21bb8cb9fb
commit
3692cc7d83
|
|
@ -23,7 +23,6 @@
|
|||
<Compile Include="Encodings.cs" />
|
||||
<Compile Include="NotNullArgument.cs" />
|
||||
<Compile Include="PlatformHelper.cs" />
|
||||
<Compile Include="PropertyActivator.cs" />
|
||||
<Compile Include="PropertyHelper.cs" />
|
||||
<Compile Include="TypeExtensions.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
// 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 System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
internal class PropertyActivator<TContext>
|
||||
{
|
||||
private readonly Func<TContext, object> _valueAccessor;
|
||||
private readonly Action<object, object> _fastPropertySetter;
|
||||
|
||||
public PropertyActivator(PropertyInfo propertyInfo,
|
||||
Func<TContext, object> valueAccessor)
|
||||
{
|
||||
PropertyInfo = propertyInfo;
|
||||
_valueAccessor = valueAccessor;
|
||||
_fastPropertySetter = PropertyHelper.MakeFastPropertySetter(propertyInfo);
|
||||
}
|
||||
|
||||
public PropertyInfo PropertyInfo { get; private set; }
|
||||
|
||||
public object Activate(object view, TContext context)
|
||||
{
|
||||
var value = _valueAccessor(context);
|
||||
_fastPropertySetter(view, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of properties on a type that are decorated with
|
||||
/// the specified activateAttributeType and have setters.
|
||||
/// </summary>
|
||||
public static PropertyActivator<TContext>[] GetPropertiesToActivate(
|
||||
Type type,
|
||||
Type activateAttributeType,
|
||||
Func<PropertyInfo, PropertyActivator<TContext>> createActivateInfo)
|
||||
{
|
||||
return type.GetRuntimeProperties()
|
||||
.Where(property =>
|
||||
property.IsDefined(activateAttributeType) &&
|
||||
property.GetIndexParameters().Length == 0 &&
|
||||
property.SetMethod != null &&
|
||||
!property.SetMethod.IsStatic)
|
||||
.Select(createActivateInfo)
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
|
|
@ -17,9 +19,10 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// </summary>
|
||||
public class DefaultControllerActivator : IControllerActivator
|
||||
{
|
||||
private readonly Func<Type, PropertyActivator<ActionContext>[]> _getPropertiesToActivate;
|
||||
private readonly IReadOnlyDictionary<Type, Func<ActionContext, object>> _valueAccessorLookup;
|
||||
private readonly ConcurrentDictionary<Type, PropertyActivator<ActionContext>[]> _injectActions;
|
||||
private readonly Func<Type, PropertyActivator[]> _getPropertiesToActivate;
|
||||
private readonly Func<PropertyInfo, PropertyActivator> _createActivateInfo;
|
||||
private readonly ReadOnlyDictionary<Type, Func<ActionContext, object>> _valueAccessorLookup;
|
||||
private readonly ConcurrentDictionary<Type, PropertyActivator[]> _injectActions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the DefaultControllerActivator class.
|
||||
|
|
@ -27,11 +30,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
public DefaultControllerActivator()
|
||||
{
|
||||
_valueAccessorLookup = CreateValueAccessorLookup();
|
||||
_injectActions = new ConcurrentDictionary<Type, PropertyActivator<ActionContext>[]>();
|
||||
_getPropertiesToActivate = type =>
|
||||
PropertyActivator<ActionContext>.GetPropertiesToActivate(type,
|
||||
typeof(ActivateAttribute),
|
||||
CreateActivateInfo);
|
||||
_getPropertiesToActivate = GetPropertiesToActivate;
|
||||
_createActivateInfo = CreateActivateInfo;
|
||||
_injectActions = new ConcurrentDictionary<Type, PropertyActivator[]>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -58,7 +59,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual IReadOnlyDictionary<Type, Func<ActionContext, object>> CreateValueAccessorLookup()
|
||||
protected virtual ReadOnlyDictionary<Type, Func<ActionContext, object>> CreateValueAccessorLookup()
|
||||
{
|
||||
var dictionary = new Dictionary<Type, Func<ActionContext, object>>
|
||||
{
|
||||
|
|
@ -77,11 +78,20 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
}
|
||||
};
|
||||
return dictionary;
|
||||
return new ReadOnlyDictionary<Type, Func<ActionContext, object>>(dictionary);
|
||||
}
|
||||
|
||||
private PropertyActivator<ActionContext> CreateActivateInfo(
|
||||
PropertyInfo property)
|
||||
private PropertyActivator[] GetPropertiesToActivate(Type controllerType)
|
||||
{
|
||||
var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
return controllerType.GetProperties(bindingFlags)
|
||||
.Where(property => property.IsDefined(typeof(ActivateAttribute)) &&
|
||||
property.GetSetMethod(nonPublic: true) != null)
|
||||
.Select(_createActivateInfo)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private PropertyActivator CreateActivateInfo(PropertyInfo property)
|
||||
{
|
||||
Func<ActionContext, object> valueAccessor;
|
||||
if (!_valueAccessorLookup.TryGetValue(property.PropertyType, out valueAccessor))
|
||||
|
|
@ -93,7 +103,29 @@ namespace Microsoft.AspNet.Mvc
|
|||
};
|
||||
}
|
||||
|
||||
return new PropertyActivator<ActionContext>(property, valueAccessor);
|
||||
return new PropertyActivator(property,
|
||||
valueAccessor);
|
||||
}
|
||||
|
||||
private sealed class PropertyActivator
|
||||
{
|
||||
private readonly PropertyInfo _propertyInfo;
|
||||
private readonly Func<ActionContext, object> _valueAccessor;
|
||||
private readonly Action<object, object> _fastPropertySetter;
|
||||
|
||||
public PropertyActivator(PropertyInfo propertyInfo,
|
||||
Func<ActionContext, object> valueAccessor)
|
||||
{
|
||||
_propertyInfo = propertyInfo;
|
||||
_valueAccessor = valueAccessor;
|
||||
_fastPropertySetter = PropertyHelper.MakeFastPropertySetter(propertyInfo);
|
||||
}
|
||||
|
||||
public void Activate(object instance, ActionContext context)
|
||||
{
|
||||
var value = _valueAccessor(context);
|
||||
_fastPropertySetter(instance, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,14 +11,11 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
public class InjectChunkVisitor : MvcCSharpCodeVisitor
|
||||
{
|
||||
private readonly List<InjectChunk> _injectChunks = new List<InjectChunk>();
|
||||
private readonly string _activateAttribute;
|
||||
|
||||
public InjectChunkVisitor([NotNull] CSharpCodeWriter writer,
|
||||
[NotNull] CodeGeneratorContext context,
|
||||
[NotNull] string activateAttributeName)
|
||||
[NotNull] CodeGeneratorContext context)
|
||||
: base(writer, context)
|
||||
{
|
||||
_activateAttribute = '[' + activateAttributeName + ']';
|
||||
}
|
||||
|
||||
public List<InjectChunk> InjectChunks
|
||||
|
|
@ -28,14 +25,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
protected override void Visit([NotNull] InjectChunk chunk)
|
||||
{
|
||||
Writer.WriteLine(_activateAttribute);
|
||||
|
||||
// Some of the chunks that we visit are either InjectDescriptors that are added by default or
|
||||
// are chunks from _ViewStart files and are not associated with any Spans. Invoking
|
||||
// CreateExpressionMapping to produce line mappings on these chunks would fail. We'll skip
|
||||
// generating code mappings for these chunks. This makes sense since the chunks do not map
|
||||
// to any code in the current view.
|
||||
if (Context.Host.DesignTimeMode && chunk.Association != null)
|
||||
if (Context.Host.DesignTimeMode)
|
||||
{
|
||||
Writer.WriteLine("public");
|
||||
var code = string.Format(CultureInfo.InvariantCulture,
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
// 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.Mvc.Razor.Host;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents information about an injected property.
|
||||
/// </summary>
|
||||
public class InjectDescriptor
|
||||
{
|
||||
public InjectDescriptor(string typeName, string memberName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(typeName))
|
||||
{
|
||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpy, "typeName");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(memberName))
|
||||
{
|
||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpy, "memberName");
|
||||
}
|
||||
|
||||
TypeName = typeName;
|
||||
MemberName = memberName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type name of the injected property
|
||||
/// </summary>
|
||||
public string TypeName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the injected property.
|
||||
/// </summary>
|
||||
public string MemberName { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@
|
|||
<Compile Include="IMvcRazorHost.cs" />
|
||||
<Compile Include="InjectChunk.cs" />
|
||||
<Compile Include="InjectChunkVisitor.cs" />
|
||||
<Compile Include="InjectDescriptor.cs" />
|
||||
<Compile Include="InjectParameterGenerator.cs" />
|
||||
<Compile Include="ModelChunk.cs" />
|
||||
<Compile Include="ModelChunkVisitor.cs" />
|
||||
|
|
@ -34,7 +33,6 @@
|
|||
<Compile Include="MvcCSharpCodeVistor.cs" />
|
||||
<Compile Include="MvcRazorCodeParser.cs" />
|
||||
<Compile Include="MvcRazorHost.cs" />
|
||||
<Compile Include="MvcRazorHostOptions.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
|
@ -13,17 +12,11 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
public class MvcCSharpCodeBuilder : CSharpCodeBuilder
|
||||
{
|
||||
private readonly MvcRazorHostOptions _hostOptions;
|
||||
|
||||
public MvcCSharpCodeBuilder([NotNull] CodeGeneratorContext context,
|
||||
[NotNull] MvcRazorHostOptions hostOptions)
|
||||
public MvcCSharpCodeBuilder([NotNull] CodeGeneratorContext context)
|
||||
: base(context)
|
||||
{
|
||||
_hostOptions = hostOptions;
|
||||
}
|
||||
|
||||
private string Model { get; set; }
|
||||
|
||||
protected override CSharpCodeWritingScope BuildClassDeclaration(CSharpCodeWriter writer)
|
||||
{
|
||||
// Grab the last model chunk so it gets intellisense.
|
||||
|
|
@ -32,8 +25,6 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var modelChunk = Context.CodeTreeBuilder.CodeTree.Chunks.OfType<ModelChunk>()
|
||||
.LastOrDefault();
|
||||
|
||||
Model = modelChunk != null ? modelChunk.ModelType : _hostOptions.DefaultModel;
|
||||
|
||||
// If there were any model chunks then we need to modify the class declaration signature.
|
||||
if (modelChunk != null)
|
||||
{
|
||||
|
|
@ -55,18 +46,26 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
protected override void BuildConstructor([NotNull] CSharpCodeWriter writer)
|
||||
{
|
||||
// TODO: Move this to a proper extension point. Right now, we don't have a place to print out properties
|
||||
// in the generated view.
|
||||
// Tracked by #773
|
||||
base.BuildConstructor(writer);
|
||||
|
||||
writer.WriteLineHiddenDirective();
|
||||
|
||||
var injectVisitor = new InjectChunkVisitor(writer, Context, _hostOptions.ActivateAttributeName);
|
||||
var injectVisitor = new InjectChunkVisitor(writer, Context);
|
||||
injectVisitor.Accept(Context.CodeTreeBuilder.CodeTree.Chunks);
|
||||
|
||||
writer.WriteLine();
|
||||
writer.WriteLineHiddenDirective();
|
||||
|
||||
var arguments = injectVisitor.InjectChunks
|
||||
.Select(chunk => new KeyValuePair<string, string>(chunk.TypeName,
|
||||
chunk.MemberName));
|
||||
using (writer.BuildConstructor("public", Context.ClassName, arguments))
|
||||
{
|
||||
foreach (var inject in injectVisitor.InjectChunks)
|
||||
{
|
||||
writer.WriteStartAssignment("this." + inject.MemberName)
|
||||
.Write(inject.MemberName)
|
||||
.WriteLine(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
|
|
@ -26,8 +24,6 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
"Microsoft.AspNet.Mvc.Rendering"
|
||||
};
|
||||
|
||||
private readonly MvcRazorHostOptions _hostOptions;
|
||||
|
||||
// CodeGenerationContext.DefaultBaseClass is set to MyBaseType<dynamic>.
|
||||
// This field holds the type name without the generic decoration (MyBaseType)
|
||||
private readonly string _baseType;
|
||||
|
|
@ -40,11 +36,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
public MvcRazorHost(string baseType)
|
||||
: base(new CSharpRazorCodeLanguage())
|
||||
{
|
||||
// TODO: this needs to flow from the application rather than being initialized here.
|
||||
// Tracked by #774
|
||||
_hostOptions = new MvcRazorHostOptions();
|
||||
_baseType = baseType;
|
||||
DefaultBaseClass = baseType + '<' + _hostOptions.DefaultModel + '>';
|
||||
DefaultBaseClass = baseType + "<dynamic>";
|
||||
GeneratedClassContext = new GeneratedClassContext(
|
||||
executeMethodName: "ExecuteAsync",
|
||||
writeMethodName: "Write",
|
||||
|
|
@ -80,34 +73,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
public override CodeBuilder DecorateCodeBuilder(CodeBuilder incomingBuilder, CodeGeneratorContext context)
|
||||
{
|
||||
UpdateCodeBuilder(context);
|
||||
return new MvcCSharpCodeBuilder(context, _hostOptions);
|
||||
}
|
||||
|
||||
private void UpdateCodeBuilder(CodeGeneratorContext context)
|
||||
{
|
||||
var currentChunks = context.CodeTreeBuilder.CodeTree.Chunks;
|
||||
var existingInjects = new HashSet<string>(currentChunks.OfType<InjectChunk>()
|
||||
.Select(c => c.MemberName),
|
||||
StringComparer.Ordinal);
|
||||
|
||||
var modelChunk = currentChunks.OfType<ModelChunk>()
|
||||
.LastOrDefault();
|
||||
var model = _hostOptions.DefaultModel;
|
||||
if (modelChunk != null)
|
||||
{
|
||||
model = modelChunk.ModelType;
|
||||
}
|
||||
model = '<' + model + '>';
|
||||
|
||||
// Locate properties by name that haven't already been injected in to the View.
|
||||
var propertiesToAdd = _hostOptions.DefaultInjectedProperties
|
||||
.Where(c => !existingInjects.Contains(c.MemberName));
|
||||
foreach (var property in propertiesToAdd)
|
||||
{
|
||||
var memberName = property.MemberName.Replace("<TModel>", model);
|
||||
currentChunks.Add(new InjectChunk(property.TypeName, memberName));
|
||||
}
|
||||
return new MvcCSharpCodeBuilder(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents configuration options for the Razor Host
|
||||
/// </summary>
|
||||
public class MvcRazorHostOptions
|
||||
{
|
||||
public MvcRazorHostOptions()
|
||||
{
|
||||
DefaultModel = "dynamic";
|
||||
ActivateAttributeName = "Microsoft.AspNet.Mvc.ActivateAttribute";
|
||||
DefaultInjectedProperties = new List<InjectDescriptor>()
|
||||
{
|
||||
new InjectDescriptor("Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<TModel>", "Html")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the model that is used by default for generated views
|
||||
/// when no model is explicily specified. Defaults to dynamic.
|
||||
/// </summary>
|
||||
public string DefaultModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the attribue that is used to decorate properties that are injected and need to
|
||||
/// be activated.
|
||||
/// </summary>
|
||||
public string ActivateAttributeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of properties that are injected by default.
|
||||
/// </summary>
|
||||
public IList<InjectDescriptor> DefaultInjectedProperties { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -10,22 +10,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Host
|
|||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNet.Mvc.Razor.Host.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Argument cannot be null or empty.
|
||||
/// </summary>
|
||||
internal static string ArgumentCannotBeNullOrEmpy
|
||||
{
|
||||
get { return GetString("ArgumentCannotBeNullOrEmpy"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Argument cannot be null or empty.
|
||||
/// </summary>
|
||||
internal static string FormatArgumentCannotBeNullOrEmpy()
|
||||
{
|
||||
return GetString("ArgumentCannotBeNullOrEmpy");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -117,9 +117,6 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ArgumentCannotBeNullOrEmpy" xml:space="preserve">
|
||||
<value>Argument cannot be null or empty.</value>
|
||||
</data>
|
||||
<data name="MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword" xml:space="preserve">
|
||||
<value>The 'inherits' keyword is not allowed when a '{0}' keyword is used.</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods to activate properties on a view instance.
|
||||
/// </summary>
|
||||
public interface IRazorViewActivator
|
||||
{
|
||||
/// <summary>
|
||||
/// When implemented in a type, activates an instantiated view.
|
||||
/// </summary>
|
||||
/// <param name="view">The view to activate.</param>
|
||||
/// <param name="context">The <see cref="ViewContext"/> for the view.</param>
|
||||
void Activate(RazorView view, ViewContext context);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,11 +30,9 @@
|
|||
<Compile Include="Compilation\RoslynCompilationService.cs" />
|
||||
<Compile Include="Extensions\DictionaryExtensions.cs" />
|
||||
<Compile Include="HelperResult.cs" />
|
||||
<Compile Include="IRazorViewActivator.cs" />
|
||||
<Compile Include="PositionTagged.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs" />
|
||||
<Compile Include="RazorView.cs" />
|
||||
<Compile Include="RazorViewActivator.cs" />
|
||||
<Compile Include="RazorViewOfT.cs" />
|
||||
<Compile Include="Razor\IRazorCompilationService.cs" />
|
||||
<Compile Include="Razor\RazorCompilationService.cs" />
|
||||
|
|
@ -44,4 +42,4 @@
|
|||
<Compile Include="ViewEngine\VirtualPathViewFactory.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -186,22 +186,6 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("SectionsNotRendered"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// View of type '{0}' cannot be instatiated by '{1}'.
|
||||
/// </summary>
|
||||
internal static string ViewCannotBeActivated
|
||||
{
|
||||
get { return GetString("ViewCannotBeActivated"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// View of type '{0}' cannot be instatiated by '{1}'.
|
||||
/// </summary>
|
||||
internal static string FormatViewCannotBeActivated(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("ViewCannotBeActivated"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// View '{0}' must have extension '{1}' when the view represents a full path.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,125 +0,0 @@
|
|||
// 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 System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class RazorViewActivator : IRazorViewActivator
|
||||
{
|
||||
private readonly ITypeActivator _typeActivator;
|
||||
private readonly ConcurrentDictionary<Type, ViewActivationInfo> _activationInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the RazorViewActivator class.
|
||||
/// </summary>
|
||||
public RazorViewActivator(ITypeActivator typeActivator)
|
||||
{
|
||||
_typeActivator = typeActivator;
|
||||
_activationInfo = new ConcurrentDictionary<Type, ViewActivationInfo>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the specified view by using the specified ViewContext.
|
||||
/// </summary>
|
||||
/// <param name="view">The view to activate.</param>
|
||||
/// <param name="context">The ViewContext for the executing view.</param>
|
||||
public void Activate([NotNull] RazorView view, [NotNull] ViewContext context)
|
||||
{
|
||||
var activationInfo = _activationInfo.GetOrAdd(view.GetType(),
|
||||
CreateViewActivationInfo);
|
||||
|
||||
context.ViewData = CreateViewDataDictionary(context, activationInfo);
|
||||
|
||||
for (var i = 0; i < activationInfo.PropertyActivators.Length; i++)
|
||||
{
|
||||
var activateInfo = activationInfo.PropertyActivators[i];
|
||||
activateInfo.Activate(view, context);
|
||||
}
|
||||
}
|
||||
|
||||
private ViewDataDictionary CreateViewDataDictionary(ViewContext context, ViewActivationInfo activationInfo)
|
||||
{
|
||||
// Create a ViewDataDictionary<TModel> if the ViewContext.ViewData is not set or the type of
|
||||
// ViewContext.ViewData is an incompatibile type.
|
||||
if (context.ViewData == null)
|
||||
{
|
||||
// Create ViewDataDictionary<TModel>(metadataProvider);
|
||||
return (ViewDataDictionary)_typeActivator.CreateInstance(context.HttpContext.RequestServices,
|
||||
activationInfo.ViewDataDictionaryType);
|
||||
}
|
||||
else if (context.ViewData.GetType() != activationInfo.ViewDataDictionaryType)
|
||||
{
|
||||
// Create ViewDataDictionary<TModel>(ViewDataDictionary);
|
||||
return (ViewDataDictionary)_typeActivator.CreateInstance(context.HttpContext.RequestServices,
|
||||
activationInfo.ViewDataDictionaryType,
|
||||
context.ViewData);
|
||||
}
|
||||
|
||||
return context.ViewData;
|
||||
}
|
||||
|
||||
private ViewActivationInfo CreateViewActivationInfo(Type type)
|
||||
{
|
||||
var typeInfo = type.GetTypeInfo();
|
||||
Type viewDataType;
|
||||
if (!typeInfo.IsGenericType || typeInfo.GenericTypeArguments.Length != 1)
|
||||
{
|
||||
// Ensure that the view is of the type RazorView<TModel>.
|
||||
var message = Resources.FormatViewCannotBeActivated(type.FullName, GetType().FullName);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var modelType = typeInfo.GenericTypeArguments[0];
|
||||
viewDataType = typeof(ViewDataDictionary<>).MakeGenericType(modelType);
|
||||
|
||||
return new ViewActivationInfo
|
||||
{
|
||||
ViewDataDictionaryType = viewDataType,
|
||||
PropertyActivators = PropertyActivator<ViewContext>.GetPropertiesToActivate(type,
|
||||
typeof(ActivateAttribute),
|
||||
CreateActivateInfo)
|
||||
};
|
||||
}
|
||||
|
||||
private PropertyActivator<ViewContext> CreateActivateInfo(PropertyInfo property)
|
||||
{
|
||||
Func<ViewContext, object> valueAccessor;
|
||||
if (property.PropertyType.IsAssignableFrom(typeof(ViewDataDictionary)))
|
||||
{
|
||||
valueAccessor = context => context.ViewData;
|
||||
}
|
||||
else
|
||||
{
|
||||
valueAccessor = context =>
|
||||
{
|
||||
var serviceProvider = context.HttpContext.RequestServices;
|
||||
var value = serviceProvider.GetService(property.PropertyType);
|
||||
var canHasViewContext = value as ICanHasViewContext;
|
||||
if (canHasViewContext != null)
|
||||
{
|
||||
canHasViewContext.Contextualize(context);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
return new PropertyActivator<ViewContext>(property, valueAccessor);
|
||||
}
|
||||
|
||||
private class ViewActivationInfo
|
||||
{
|
||||
public PropertyActivator<ViewContext>[] PropertyActivators { get; set; }
|
||||
|
||||
public Type ViewDataDictionaryType { get; set; }
|
||||
|
||||
public Action<object, object> ViewDataDictionarySetter { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
// 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.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
|
|
@ -16,15 +19,43 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
}
|
||||
}
|
||||
|
||||
[Activate]
|
||||
public ViewDataDictionary<TModel> ViewData { get; set; }
|
||||
public ViewDataDictionary<TModel> ViewData { get; private set; }
|
||||
|
||||
public IHtmlHelper<TModel> Html { get; set; }
|
||||
|
||||
public override Task RenderAsync([NotNull] ViewContext context)
|
||||
{
|
||||
var viewActivator = context.HttpContext.RequestServices.GetService<IRazorViewActivator>();
|
||||
viewActivator.Activate(this, context);
|
||||
ViewData = context.ViewData as ViewDataDictionary<TModel>;
|
||||
if (ViewData == null)
|
||||
{
|
||||
if (context.ViewData != null)
|
||||
{
|
||||
ViewData = new ViewDataDictionary<TModel>(context.ViewData);
|
||||
}
|
||||
else
|
||||
{
|
||||
var metadataProvider = context.HttpContext.RequestServices.GetService<IModelMetadataProvider>();
|
||||
ViewData = new ViewDataDictionary<TModel>(metadataProvider);
|
||||
}
|
||||
|
||||
// Have new ViewDataDictionary; make sure it's visible everywhere.
|
||||
context.ViewData = ViewData;
|
||||
}
|
||||
|
||||
InitHelpers(context);
|
||||
|
||||
return base.RenderAsync(context);
|
||||
}
|
||||
|
||||
private void InitHelpers(ViewContext context)
|
||||
{
|
||||
Html = context.HttpContext.RequestServices.GetService<IHtmlHelper<TModel>>();
|
||||
|
||||
var contextable = Html as ICanHasViewContext;
|
||||
if (contextable != null)
|
||||
{
|
||||
contextable.Contextualize(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,9 +150,6 @@
|
|||
<data name="SectionsNotRendered" xml:space="preserve">
|
||||
<value>The following sections have been defined but have not been rendered: '{0}'.</value>
|
||||
</data>
|
||||
<data name="ViewCannotBeActivated" xml:space="preserve">
|
||||
<value>View of type '{0}' cannot be instatiated by '{1}'.</value>
|
||||
</data>
|
||||
<data name="ViewMustEndInExtension" xml:space="preserve">
|
||||
<value>View '{0}' must have extension '{1}' when the view represents a full path.</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
yield return describe.Scoped<ICompositeViewEngine, CompositeViewEngine>();
|
||||
yield return describe.Transient<IRazorCompilationService, RazorCompilationService>();
|
||||
yield return describe.Transient<IVirtualPathViewFactory, VirtualPathViewFactory>();
|
||||
yield return describe.Singleton<IRazorViewActivator, RazorViewActivator>();
|
||||
|
||||
yield return describe.Transient<INestedProvider<ActionDescriptorProviderContext>,
|
||||
ReflectedActionDescriptorProvider>();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var writer = new CSharpCodeWriter();
|
||||
var context = CreateContext();
|
||||
|
||||
var visitor = new InjectChunkVisitor(writer, context, "ActivateAttribute");
|
||||
var visitor = new InjectChunkVisitor(writer, context);
|
||||
|
||||
// Act
|
||||
visitor.Accept(new Chunk[]
|
||||
|
|
@ -41,15 +41,13 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
// Arrange
|
||||
var expected =
|
||||
@"[ActivateAttribute]
|
||||
public MyType1 MyPropertyName1 { get; private set; }
|
||||
[ActivateAttribute]
|
||||
@"public MyType1 MyPropertyName1 { get; private set; }
|
||||
public MyType2 @MyPropertyName2 { get; private set; }
|
||||
";
|
||||
var writer = new CSharpCodeWriter();
|
||||
var context = CreateContext();
|
||||
|
||||
var visitor = new InjectChunkVisitor(writer, context, "ActivateAttribute");
|
||||
var visitor = new InjectChunkVisitor(writer, context);
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
var node = (Span)factory.Code("Some code")
|
||||
.As(new InjectParameterGenerator("MyType", "MyPropertyName"));
|
||||
|
|
@ -71,15 +69,13 @@ public MyType2 @MyPropertyName2 { get; private set; }
|
|||
public void Visit_WithDesignTimeHost_GeneratesPropertiesAndLinePragmas_ForInjectChunks()
|
||||
{
|
||||
// Arrange
|
||||
var expected = @"[Microsoft.AspNet.Mvc.ActivateAttribute]
|
||||
public
|
||||
var expected = @"public
|
||||
#line 1 """"
|
||||
MyType1 MyPropertyName1
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
{ get; private set; }
|
||||
[Microsoft.AspNet.Mvc.ActivateAttribute]
|
||||
public
|
||||
#line 1 """"
|
||||
MyType2 @MyPropertyName2
|
||||
|
|
@ -92,7 +88,7 @@ MyType2 @MyPropertyName2
|
|||
var context = CreateContext();
|
||||
context.Host.DesignTimeMode = true;
|
||||
|
||||
var visitor = new InjectChunkVisitor(writer, context, "Microsoft.AspNet.Mvc.ActivateAttribute");
|
||||
var visitor = new InjectChunkVisitor(writer, context);
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
var node = (Span)factory.Code("Some code")
|
||||
.As(new InjectParameterGenerator("MyType", "MyPropertyName"));
|
||||
|
|
@ -125,40 +121,7 @@ MyType2 @MyPropertyName2
|
|||
var expectedLineMappings = new List<LineMapping>
|
||||
{
|
||||
BuildLineMapping(1, 0, 1, 32, 3, 0, 17),
|
||||
BuildLineMapping(28, 1, 8, 573, 26, 8, 20)
|
||||
};
|
||||
|
||||
// Act
|
||||
GeneratorResults results;
|
||||
using (var buffer = new StringTextBuffer(source))
|
||||
{
|
||||
results = engine.GenerateCode(buffer);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.True(results.Success);
|
||||
Assert.Equal(expectedCode, results.GeneratedCode);
|
||||
Assert.Empty(results.ParserErrors);
|
||||
Assert.Equal(expectedLineMappings, results.DesignTimeLineMappings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InjectVisitorWithModel_GeneratesCorrectLineMappings()
|
||||
{
|
||||
// Arrange
|
||||
var host = new MvcRazorHost("RazorView")
|
||||
{
|
||||
DesignTimeMode = true
|
||||
};
|
||||
host.NamespaceImports.Clear();
|
||||
var engine = new RazorTemplateEngine(host);
|
||||
var source = ReadResource("TestFiles/Input/InjectWithModel.cshtml");
|
||||
var expectedCode = ReadResource("TestFiles/Output/InjectWithModel.cs");
|
||||
var expectedLineMappings = new List<LineMapping>
|
||||
{
|
||||
BuildLineMapping(7, 0, 7, 126, 6, 7, 7),
|
||||
BuildLineMapping(24, 1, 8, 562, 26, 8, 20),
|
||||
BuildLineMapping(54, 2, 8, 732, 34, 8, 22)
|
||||
BuildLineMapping(28, 1, 8, 442, 21, 8, 20)
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@
|
|||
<Compile Include="SpanFactory\SpanFactoryExtensions.cs" />
|
||||
<Compile Include="SpanFactory\UnclassifiedSpanConstructor.cs" />
|
||||
<Compile Include="StringTextBuffer.cs" />
|
||||
<Compile Include="TestFiles\Input\InjectWithModel.cshtml" />
|
||||
<Compile Include="TestFiles\Output\InjectWithModel.cs" />
|
||||
<Compile Include="TestFiles\Output\Model.cs" />
|
||||
<Compile Include="TestFiles\Output\Inject.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
@model MyModel
|
||||
@inject MyApp MyPropertyName
|
||||
@inject MyService<TModel> Html
|
||||
|
|
@ -17,11 +17,6 @@ using MyNamespace
|
|||
#pragma warning restore 219
|
||||
}
|
||||
#line hidden
|
||||
public __CompiledTemplate()
|
||||
{
|
||||
}
|
||||
#line hidden
|
||||
[Microsoft.AspNet.Mvc.ActivateAttribute]
|
||||
public
|
||||
#line 2 ""
|
||||
MyApp MyPropertyName
|
||||
|
|
@ -29,10 +24,12 @@ using MyNamespace
|
|||
#line default
|
||||
#line hidden
|
||||
{ get; private set; }
|
||||
[Microsoft.AspNet.Mvc.ActivateAttribute]
|
||||
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<TModel> Html { get; private set; }
|
||||
|
||||
#line hidden
|
||||
public __CompiledTemplate(MyApp MyPropertyName)
|
||||
{
|
||||
this.MyPropertyName = MyPropertyName;
|
||||
}
|
||||
|
||||
#pragma warning disable 1998
|
||||
public override async Task ExecuteAsync()
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
namespace Razor
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class __CompiledTemplate : RazorView<
|
||||
#line 1 ""
|
||||
MyModel
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
>
|
||||
{
|
||||
private static object @__o;
|
||||
private void @__RazorDesignTimeHelpers__()
|
||||
{
|
||||
#pragma warning disable 219
|
||||
#pragma warning restore 219
|
||||
}
|
||||
#line hidden
|
||||
public __CompiledTemplate()
|
||||
{
|
||||
}
|
||||
#line hidden
|
||||
[Microsoft.AspNet.Mvc.ActivateAttribute]
|
||||
public
|
||||
#line 2 ""
|
||||
MyApp MyPropertyName
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
{ get; private set; }
|
||||
[Microsoft.AspNet.Mvc.ActivateAttribute]
|
||||
public
|
||||
#line 3 ""
|
||||
MyService<TModel> Html
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
{ get; private set; }
|
||||
|
||||
#line hidden
|
||||
|
||||
#pragma warning disable 1998
|
||||
public override async Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
}
|
||||
|
|
@ -16,15 +16,12 @@
|
|||
#pragma warning disable 219
|
||||
#pragma warning restore 219
|
||||
}
|
||||
#line hidden
|
||||
|
||||
#line hidden
|
||||
public __CompiledTemplate()
|
||||
{
|
||||
}
|
||||
#line hidden
|
||||
[Microsoft.AspNet.Mvc.ActivateAttribute]
|
||||
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<TModel> Html { get; private set; }
|
||||
|
||||
#line hidden
|
||||
|
||||
#pragma warning disable 1998
|
||||
public override async Task ExecuteAsync()
|
||||
|
|
|
|||
|
|
@ -23,10 +23,9 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="MvcRazorCodeParserTest.cs" />
|
||||
<Compile Include="RazorCompilationServiceTest.cs" />
|
||||
<Compile Include="RazorViewActivatorTest.cs" />
|
||||
<Compile Include="RazorViewEngineTest.cs" />
|
||||
<Compile Include="RazorViewTest.cs" />
|
||||
<Compile Include="SpanFactory.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
// 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 System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public class RazorViewActivatorTest
|
||||
{
|
||||
[Fact]
|
||||
public void Activate_ActivatesAndContextualizesPropertiesOnViews()
|
||||
{
|
||||
// Arrange
|
||||
var activator = new RazorViewActivator();
|
||||
var instance = new TestView();
|
||||
|
||||
var myService = new MyService();
|
||||
var helper = Mock.Of<IHtmlHelper<object>>();
|
||||
var serviceProvider = new Mock<IServiceProvider>();
|
||||
serviceProvider.Setup(p => p.GetService(typeof(MyService)))
|
||||
.Returns(myService);
|
||||
serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>)))
|
||||
.Returns(helper);
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.RequestServices)
|
||||
.Returns(serviceProvider.Object);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var actionContext = new ActionContext(routeContext, new ActionDescriptor());
|
||||
var viewContext = new ViewContext(actionContext,
|
||||
instance,
|
||||
new ViewDataDictionary(Mock.Of<IModelMetadataProvider>()),
|
||||
TextWriter.Null);
|
||||
// Act
|
||||
activator.Activate(instance, viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.Same(helper, instance.Html);
|
||||
Assert.Same(myService, instance.MyService);
|
||||
Assert.Same(viewContext, myService.ViewContext);
|
||||
Assert.Null(instance.MyService2);
|
||||
}
|
||||
|
||||
private abstract class TestViewBase : RazorView
|
||||
{
|
||||
[Activate]
|
||||
public MyService MyService { get; set; }
|
||||
|
||||
public MyService MyService2 { get; set; }
|
||||
}
|
||||
|
||||
private class TestView : TestViewBase
|
||||
{
|
||||
[Activate]
|
||||
internal IHtmlHelper<object> Html { get; private set; }
|
||||
|
||||
public override Task ExecuteAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class MyService : ICanHasViewContext
|
||||
{
|
||||
public ViewContext ViewContext { get; private set; }
|
||||
|
||||
public void Contextualize(ViewContext viewContext)
|
||||
{
|
||||
ViewContext = viewContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue