Add IComponentActivator
This commit is contained in:
parent
156023d3f9
commit
dae55edfec
|
|
@ -6,6 +6,7 @@ using System.Collections.Concurrent;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Components.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
|
|
@ -25,7 +26,12 @@ namespace Microsoft.AspNetCore.Components
|
|||
|
||||
public IComponent InstantiateComponent(IServiceProvider serviceProvider, Type componentType)
|
||||
{
|
||||
var instance = Activator.CreateInstance(componentType);
|
||||
var activator = serviceProvider.GetService<IComponentActivator>();
|
||||
|
||||
var instance = activator != null
|
||||
? activator.CreateInstance(componentType)
|
||||
: Activator.CreateInstance(componentType);
|
||||
|
||||
if (!(instance is IComponent component))
|
||||
{
|
||||
throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// 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.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of component activator.
|
||||
/// </summary>
|
||||
public class DefaultComponentActivator : IComponentActivator
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IComponent? CreateInstance(Type componentType)
|
||||
{
|
||||
return Activator.CreateInstance(componentType) as IComponent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// 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.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an activator that can be used to instantiate components.
|
||||
/// </summary>
|
||||
public interface IComponentActivator
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an component of the specified type using that type's default constructor.
|
||||
/// </summary>
|
||||
/// <param name="componentType">The type of component to create.</param>
|
||||
/// <returns>A reference to the newly created component.</returns>
|
||||
IComponent? CreateInstance(Type componentType);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,32 @@ namespace Microsoft.AspNetCore.Components
|
|||
Assert.IsType<EmptyComponent>(instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InstantiateComponent_CreatesInstance_WithActivator()
|
||||
{
|
||||
// Arrange
|
||||
var componentType = typeof(EmptyComponent);
|
||||
var factory = new ComponentFactory();
|
||||
|
||||
// Act
|
||||
var instance = factory.InstantiateComponent(GetServiceProviderWithActivator(), componentType);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(instance);
|
||||
Assert.IsType<EmptyComponent>(instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InstantiateComponent_CreatesInstance_WithActivator_NonComponent()
|
||||
{
|
||||
// Arrange
|
||||
var componentType = typeof(NonComponent);
|
||||
var factory = new ComponentFactory();
|
||||
|
||||
// Assert
|
||||
Assert.Throws<ArgumentException>(()=>factory.InstantiateComponent(GetServiceProviderWithActivator(), componentType));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InstantiateComponent_AssignsPropertiesWithInjectAttribute()
|
||||
{
|
||||
|
|
@ -96,6 +122,15 @@ namespace Microsoft.AspNetCore.Components
|
|||
.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private static IServiceProvider GetServiceProviderWithActivator()
|
||||
{
|
||||
return new ServiceCollection()
|
||||
.AddTransient<TestService1>()
|
||||
.AddTransient<TestService2>()
|
||||
.AddSingleton<IComponentActivator, DefaultComponentActivator>()
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private class EmptyComponent : IComponent
|
||||
{
|
||||
public void Attach(RenderHandle renderHandle)
|
||||
|
|
@ -162,6 +197,8 @@ namespace Microsoft.AspNetCore.Components
|
|||
public TestService2 Property5 { get; set; }
|
||||
}
|
||||
|
||||
private class NonComponent { }
|
||||
|
||||
public class TestService1 { }
|
||||
public class TestService2 { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.AddScoped<IJSRuntime, RemoteJSRuntime>();
|
||||
services.AddScoped<INavigationInterception, RemoteNavigationInterception>();
|
||||
services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
|
||||
services.AddScoped<IComponentActivator, DefaultComponentActivator>();
|
||||
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<CircuitOptions>, CircuitOptionsJSInteropDetailedErrorsConfiguration>());
|
||||
|
||||
|
|
|
|||
|
|
@ -212,12 +212,13 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddScoped<NavigationManager, HttpNavigationManager>();
|
||||
services.TryAddScoped<IJSRuntime, UnsupportedJavaScriptRuntime>();
|
||||
services.TryAddScoped<INavigationInterception, UnsupportedNavigationInterception>();
|
||||
|
||||
|
||||
services.TryAddTransient<ControllerSaveTempDataPropertyFilter>();
|
||||
|
||||
// This does caching so it should stay singleton
|
||||
services.TryAddSingleton<ITempDataProvider, CookieTempDataProvider>();
|
||||
services.TryAddSingleton<TempDataSerializer, DefaultTempDataSerializer>();
|
||||
services.TryAddSingleton<IComponentActivator, DefaultComponentActivator>();
|
||||
|
||||
//
|
||||
// Antiforgery
|
||||
|
|
|
|||
Loading…
Reference in New Issue