parent
75df24e357
commit
45a72a0e18
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
|
@ -17,6 +19,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public class RazorPageActivator : IRazorPageActivator
|
public class RazorPageActivator : IRazorPageActivator
|
||||||
{
|
{
|
||||||
|
private delegate ViewDataDictionary CreateViewDataNested(ViewDataDictionary source);
|
||||||
|
private delegate ViewDataDictionary CreateViewDataRoot(
|
||||||
|
IModelMetadataProvider metadataProvider,
|
||||||
|
ModelStateDictionary modelState);
|
||||||
|
|
||||||
// Name of the "public TModel Model" property on RazorPage<TModel>
|
// Name of the "public TModel Model" property on RazorPage<TModel>
|
||||||
private const string ModelPropertyName = "Model";
|
private const string ModelPropertyName = "Model";
|
||||||
private readonly ConcurrentDictionary<Type, PageActivationInfo> _activationInfo;
|
private readonly ConcurrentDictionary<Type, PageActivationInfo> _activationInfo;
|
||||||
|
|
@ -63,17 +70,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
if (context.ViewData == null)
|
if (context.ViewData == null)
|
||||||
{
|
{
|
||||||
// Create ViewDataDictionary<TModel>(IModelMetadataProvider, ModelStateDictionary).
|
// Create ViewDataDictionary<TModel>(IModelMetadataProvider, ModelStateDictionary).
|
||||||
return (ViewDataDictionary)Activator.CreateInstance(
|
return activationInfo.CreateViewDataRoot(
|
||||||
activationInfo.ViewDataDictionaryType,
|
|
||||||
_metadataProvider,
|
_metadataProvider,
|
||||||
context.ModelState);
|
context.ModelState);
|
||||||
}
|
}
|
||||||
else if (context.ViewData.GetType() != activationInfo.ViewDataDictionaryType)
|
else if (context.ViewData.GetType() != activationInfo.ViewDataDictionaryType)
|
||||||
{
|
{
|
||||||
// Create ViewDataDictionary<TModel>(ViewDataDictionary).
|
// Create ViewDataDictionary<TModel>(ViewDataDictionary).
|
||||||
return (ViewDataDictionary)Activator.CreateInstance(
|
return activationInfo.CreateViewDataNested(context.ViewData);
|
||||||
activationInfo.ViewDataDictionaryType,
|
|
||||||
context.ViewData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.ViewData;
|
return context.ViewData;
|
||||||
|
|
@ -96,6 +100,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
return new PageActivationInfo
|
return new PageActivationInfo
|
||||||
{
|
{
|
||||||
ViewDataDictionaryType = viewDataType,
|
ViewDataDictionaryType = viewDataType,
|
||||||
|
CreateViewDataNested = GetCreateViewDataNested(viewDataType),
|
||||||
|
CreateViewDataRoot = GetCreateViewDataRoot(viewDataType),
|
||||||
PropertyActivators = PropertyActivator<ViewContext>.GetPropertiesToActivate(
|
PropertyActivators = PropertyActivator<ViewContext>.GetPropertiesToActivate(
|
||||||
type,
|
type,
|
||||||
typeof(RazorInjectAttribute),
|
typeof(RazorInjectAttribute),
|
||||||
|
|
@ -104,6 +110,41 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CreateViewDataNested GetCreateViewDataNested(Type viewDataDictionaryType)
|
||||||
|
{
|
||||||
|
var parameterTypes = new Type[] { typeof(ViewDataDictionary) };
|
||||||
|
var matchingConstructor = viewDataDictionaryType.GetConstructor(parameterTypes);
|
||||||
|
Debug.Assert(matchingConstructor != null);
|
||||||
|
|
||||||
|
var parameters = new ParameterExpression[] { Expression.Parameter(parameterTypes[0]) };
|
||||||
|
var newExpression = Expression.New(matchingConstructor, parameters);
|
||||||
|
var castNewCall = Expression.Convert(
|
||||||
|
newExpression,
|
||||||
|
typeof(ViewDataDictionary));
|
||||||
|
var lambda = Expression.Lambda<CreateViewDataNested>(castNewCall, parameters);
|
||||||
|
return lambda.Compile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CreateViewDataRoot GetCreateViewDataRoot(Type viewDataDictionaryType)
|
||||||
|
{
|
||||||
|
var parameterTypes = new Type[] {
|
||||||
|
typeof(IModelMetadataProvider),
|
||||||
|
typeof(ModelStateDictionary) };
|
||||||
|
var matchingConstructor = viewDataDictionaryType.GetConstructor(parameterTypes);
|
||||||
|
Debug.Assert(matchingConstructor != null);
|
||||||
|
|
||||||
|
var parameters = new ParameterExpression[] {
|
||||||
|
Expression.Parameter(parameterTypes[0]),
|
||||||
|
Expression.Parameter(parameterTypes[1]) };
|
||||||
|
var newExpression = Expression.New(matchingConstructor, parameters);
|
||||||
|
var castNewCall = Expression.Convert(
|
||||||
|
newExpression,
|
||||||
|
typeof(ViewDataDictionary));
|
||||||
|
var lambda = Expression.Lambda<CreateViewDataRoot>(castNewCall, parameters);
|
||||||
|
return lambda.Compile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private PropertyActivator<ViewContext> CreateActivateInfo(PropertyInfo property)
|
private PropertyActivator<ViewContext> CreateActivateInfo(PropertyInfo property)
|
||||||
{
|
{
|
||||||
Func<ViewContext, object> valueAccessor;
|
Func<ViewContext, object> valueAccessor;
|
||||||
|
|
@ -147,6 +188,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
|
|
||||||
public Type ViewDataDictionaryType { get; set; }
|
public Type ViewDataDictionaryType { get; set; }
|
||||||
|
|
||||||
|
public CreateViewDataNested CreateViewDataNested { get; set; }
|
||||||
|
|
||||||
|
public CreateViewDataRoot CreateViewDataRoot { get; set; }
|
||||||
|
|
||||||
public Action<object, object> ViewDataDictionarySetter { get; set; }
|
public Action<object, object> ViewDataDictionarySetter { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue