This repository has been archived by the owner on Dec 14, 2018. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introducing IPageModelActivatorProvider
Fixes #5480
- Loading branch information
Showing
9 changed files
with
595 additions
and
18 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
src/Microsoft.AspNetCore.Mvc.RazorPages/IPageModelActivatorProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
|
||
namespace Microsoft.AspNetCore.Mvc.RazorPages | ||
{ | ||
/// <summary> | ||
/// Provides methods to create a Razor page model. | ||
/// </summary> | ||
public interface IPageModelActivatorProvider | ||
{ | ||
/// <summary> | ||
/// Creates a Razor page model activator. | ||
/// </summary> | ||
/// <param name="descriptor">The <see cref="CompiledPageActionDescriptor"/>.</param> | ||
/// <returns>The delegate used to activate the page model.</returns> | ||
Func<PageContext, object> CreateActivator(CompiledPageActionDescriptor descriptor); | ||
|
||
/// <summary> | ||
/// Releases a Razor page model. | ||
/// </summary> | ||
/// <param name="descriptor">The <see cref="CompiledPageActionDescriptor"/>.</param> | ||
/// <returns>The delegate used to dispose the activated page model.</returns> | ||
Action<PageContext, object> CreateReleaser(CompiledPageActionDescriptor descriptor); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
src/Microsoft.AspNetCore.Mvc.RazorPages/IPageModelFactoryProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
|
||
namespace Microsoft.AspNetCore.Mvc.RazorPages | ||
{ | ||
/// <summary> | ||
/// Provides methods for creation and disposal of Razor page models. | ||
/// </summary> | ||
public interface IPageModelFactoryProvider | ||
{ | ||
/// <summary> | ||
/// Creates a factory for producing models for Razor pages given the specified <see cref="PageContext"/>. | ||
/// </summary> | ||
/// <param name="descriptor">The <see cref="CompiledPageActionDescriptor"/>.</param> | ||
/// <returns>The Razor page model factory.</returns> | ||
Func<PageContext, object> CreateModelFactory(CompiledPageActionDescriptor descriptor); | ||
|
||
/// <summary> | ||
/// Releases a Razor page model. | ||
/// </summary> | ||
/// <param name="descriptor">The <see cref="CompiledPageActionDescriptor"/>.</param> | ||
/// <returns>The delegate used to release the created page model.</returns> | ||
Action<PageContext, object> CreateModelDisposer(CompiledPageActionDescriptor descriptor); | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/DefaultPageModelActivatorProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright (c) .NET Foundation. 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.Reflection; | ||
using Microsoft.AspNetCore.Mvc.Internal; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal | ||
{ | ||
/// <summary> | ||
/// <see cref="IPageActivatorProvider"/> that uses type activation to create Pages. | ||
/// </summary> | ||
public class DefaultPageModelActivatorProvider : IPageModelActivatorProvider | ||
{ | ||
private readonly Action<PageContext, object> _disposer = Dispose; | ||
|
||
/// <inheritdoc /> | ||
public virtual Func<PageContext, object> CreateActivator(CompiledPageActionDescriptor actionDescriptor) | ||
{ | ||
if (actionDescriptor == null) | ||
{ | ||
throw new ArgumentNullException(nameof(actionDescriptor)); | ||
} | ||
|
||
var modelTypeInfo = actionDescriptor.ModelTypeInfo?.AsType(); | ||
if (modelTypeInfo == null) | ||
{ | ||
throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( | ||
nameof(actionDescriptor.ModelTypeInfo), | ||
nameof(actionDescriptor)), | ||
nameof(actionDescriptor)); | ||
} | ||
|
||
var factory = ActivatorUtilities.CreateFactory(modelTypeInfo, Type.EmptyTypes); | ||
return (context) => factory(context.HttpContext.RequestServices, EmptyArray<object>.Instance); | ||
} | ||
|
||
public virtual Action<PageContext, object> CreateReleaser(CompiledPageActionDescriptor actionDescriptor) | ||
{ | ||
if (actionDescriptor == null) | ||
{ | ||
throw new ArgumentNullException(nameof(actionDescriptor)); | ||
} | ||
|
||
if (typeof(IDisposable).GetTypeInfo().IsAssignableFrom(actionDescriptor.ModelTypeInfo)) | ||
{ | ||
return _disposer; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
private static void Dispose(PageContext context, object page) | ||
{ | ||
if (context == null) | ||
{ | ||
throw new ArgumentNullException(nameof(context)); | ||
} | ||
|
||
if (page == null) | ||
{ | ||
throw new ArgumentNullException(nameof(page)); | ||
} | ||
|
||
((IDisposable)page).Dispose(); | ||
} | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/DefaultPageModelFactoryProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Copyright (c) .NET Foundation. 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.Reflection; | ||
using Microsoft.Extensions.Internal; | ||
|
||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal | ||
{ | ||
public class DefaultPageModelFactoryProvider : IPageModelFactoryProvider | ||
{ | ||
private static readonly Func<PropertyInfo, PropertyActivator<PageContext>> _createActivateInfo = | ||
CreateActivateInfo; | ||
private readonly IPageModelActivatorProvider _modelActivator; | ||
|
||
public DefaultPageModelFactoryProvider(IPageModelActivatorProvider modelActivator) | ||
{ | ||
_modelActivator = modelActivator; | ||
} | ||
|
||
public virtual Func<PageContext, object> CreateModelFactory(CompiledPageActionDescriptor descriptor) | ||
{ | ||
if (descriptor == null) | ||
{ | ||
throw new ArgumentNullException(nameof(descriptor)); | ||
} | ||
|
||
if (descriptor.ModelTypeInfo == null) | ||
{ | ||
return null; | ||
} | ||
|
||
var modelActivator = _modelActivator.CreateActivator(descriptor); | ||
var propertyActivator = PropertyActivator<PageContext>.GetPropertiesToActivate( | ||
descriptor.ModelTypeInfo.AsType(), | ||
typeof(PageContextAttribute), | ||
_createActivateInfo, | ||
includeNonPublic: false); | ||
|
||
return pageContext => | ||
{ | ||
var model = modelActivator(pageContext); | ||
for (var i = 0; i < propertyActivator.Length; i++) | ||
{ | ||
propertyActivator[i].Activate(model, pageContext); | ||
} | ||
return model; | ||
}; | ||
} | ||
|
||
public virtual Action<PageContext, object> CreateModelDisposer(CompiledPageActionDescriptor descriptor) | ||
{ | ||
if (descriptor == null) | ||
{ | ||
throw new ArgumentNullException(nameof(descriptor)); | ||
} | ||
|
||
if (descriptor.ModelTypeInfo == null) | ||
{ | ||
return null; | ||
} | ||
|
||
return _modelActivator.CreateReleaser(descriptor); | ||
} | ||
|
||
private static PropertyActivator<PageContext> CreateActivateInfo(PropertyInfo property) => | ||
new PropertyActivator<PageContext>(property, pageContext => pageContext); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
src/Microsoft.AspNetCore.Mvc.RazorPages/PageContextAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
|
||
namespace Microsoft.AspNetCore.Mvc.RazorPages | ||
{ | ||
/// <summary> | ||
/// Specifies that a Razor Page model property should be set with the current <see cref="PageContext"/> when creating | ||
/// the model instance. The property must have a public set method. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] | ||
public class PageContextAttribute : Attribute | ||
{ | ||
} | ||
} |
Oops, something went wrong.