In preparation for DI, give every Renderer an IServiceProvider

This commit is contained in:
Steve Sanderson 2018-02-22 16:06:33 +00:00
parent dfe576f4fa
commit ce10e6fa19
12 changed files with 111 additions and 11 deletions

View File

@ -2,11 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Blazor.Browser.Interop;
using Microsoft.AspNetCore.Blazor.Browser.Services;
using Microsoft.AspNetCore.Blazor.Components;
using Microsoft.AspNetCore.Blazor.Rendering;
using Microsoft.AspNetCore.Blazor.RenderTree;
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
{
@ -21,7 +21,15 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
/// <summary>
/// Constructs an instance of <see cref="BrowserRenderer"/>.
/// </summary>
public BrowserRenderer()
public BrowserRenderer(): this(new DefaultBrowserServiceProvider())
{
}
/// <summary>
/// Constructs an instance of <see cref="BrowserRenderer"/>.
/// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> to use when initializing components.</param>
public BrowserRenderer(IServiceProvider serviceProvider): base(serviceProvider)
{
_browserRendererId = BrowserRendererRegistry.Add(this);
}

View File

@ -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.Blazor.Browser.Services
{
/// <summary>
/// An implementation of <see cref="IServiceProvider"/> configured with
/// default services suitable for use in a browser environment.
/// </summary>
public class DefaultBrowserServiceProvider : IServiceProvider
{
/// <inheritdoc />
public object GetService(Type serviceType)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,36 @@
// 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.Blazor.Components
{
internal class ComponentFactory
{
private readonly IServiceProvider _serviceProvider;
public ComponentFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider
?? throw new ArgumentNullException(nameof(serviceProvider));
}
public IComponent InstantiateComponent(Type componentType)
{
if (!typeof(IComponent).IsAssignableFrom(componentType))
{
throw new ArgumentException($"The type {componentType.FullName} does not " +
$"implement {nameof(IComponent)}.", nameof(componentType));
}
var instance = (IComponent)Activator.CreateInstance(componentType);
PerformPropertyInjection(instance);
return instance;
}
private void PerformPropertyInjection(IComponent instance)
{
// TODO
}
}
}

View File

@ -2,3 +2,4 @@
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Test")]
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Browser.Test")]
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Build.Test")]

View File

@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
/// </summary>
public abstract class Renderer
{
private readonly ComponentFactory _componentFactory;
private int _nextComponentId = 0; // TODO: change to 'long' when Mono .NET->JS interop supports it
private readonly Dictionary<int, ComponentState> _componentStateById
= new Dictionary<int, ComponentState>();
@ -25,20 +26,22 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
private readonly Dictionary<int, UIEventHandler> _eventHandlersById
= new Dictionary<int, UIEventHandler>();
/// <summary>
/// Constructs an instance of <see cref="Renderer"/>.
/// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> to be used when initialising components.</param>
public Renderer(IServiceProvider serviceProvider)
{
_componentFactory = new ComponentFactory(serviceProvider);
}
/// <summary>
/// Constructs a new component of the specified type.
/// </summary>
/// <param name="componentType">The type of the component to instantiate.</param>
/// <returns>The component instance.</returns>
protected IComponent InstantiateComponent(Type componentType)
{
if (!typeof(IComponent).IsAssignableFrom(componentType))
{
throw new ArgumentException($"Must implement {nameof(IComponent)}", nameof(componentType));
}
return (IComponent)Activator.CreateInstance(componentType);
}
=> _componentFactory.InstantiateComponent(componentType);
/// <summary>
/// Associates the <see cref="IComponent"/> with the <see cref="Renderer"/>, assigning

View File

@ -18,7 +18,7 @@
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Blazor.Build\Microsoft.AspNetCore.Blazor.Build.csproj" />
<!-- Shared sources -->
<Compile Include="..\shared\AssertFrame.cs" Link="Helpers\AssertFrame.cs" />
<Compile Include="..\shared\**\*.cs" Link="Helpers\%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>

View File

@ -745,6 +745,10 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
private class TestRenderer : Renderer
{
public TestRenderer() : base(new TestServiceProvider())
{
}
public RenderTreeFrame[] LatestBatchReferenceFrames { get; private set; }
public void AttachComponent(IComponent component)

View File

@ -396,6 +396,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
private class TestRenderer : Renderer
{
public TestRenderer() : base(new TestServiceProvider())
{
}
protected override void UpdateDisplay(RenderBatch renderBatch)
=> throw new NotImplementedException();
}

View File

@ -922,6 +922,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
private class FakeRenderer : Renderer
{
public FakeRenderer() : base(new TestServiceProvider())
{
}
protected override void UpdateDisplay(RenderBatch renderBatch)
{
}

View File

@ -865,6 +865,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
private class NoOpRenderer : Renderer
{
public NoOpRenderer() : base(new TestServiceProvider())
{
}
public new int AssignComponentId(IComponent component)
=> base.AssignComponentId(component);

View File

@ -11,6 +11,10 @@ namespace Microsoft.AspNetCore.Blazor.Test.Helpers
{
public class TestRenderer : Renderer
{
public TestRenderer(): base(new TestServiceProvider())
{
}
public List<CapturedBatch> Batches { get; }
= new List<CapturedBatch>();

View File

@ -0,0 +1,12 @@
// 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.Blazor.Test.Helpers
{
public class TestServiceProvider : IServiceProvider
{
public object GetService(Type serviceType) => throw new NotImplementedException();
}
}