-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRazor.cs
106 lines (93 loc) · 4.48 KB
/
Razor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using XF = Xamarin.Forms;
namespace LivingThing.Core.Frameworks.XamarinRazor
{
public partial class Razor<TRazorComponent> : XF.ContentPage where TRazorComponent : ComponentBase
{
public Razor(IServiceProvider serviceProvider, Action<TRazorComponent> parameterSetter = null)
{
var renderer = new RazorComponentRenderer(serviceProvider);
renderer.AddComponent<TRazorComponent, XF.Element>(this, parameterSetter);
}
}
public interface IDisposableElement<TElement> : IDisposable where TElement : class
{
public TElement Element { get; }
public void ReRender();
}
internal class DisposableElement<TElement>: IDisposableElement<TElement> where TElement:class
{
internal DisposableElement(TElement element, RazorComponentRenderer renderer)
{
Element = element;
Renderer = renderer;
}
public TElement Element { get; }
public RazorComponentRenderer Renderer { get; }
public void Dispose()
{
Renderer.Dispose();
}
public void ReRender()
{
Renderer.ReRender();
}
}
public static class Razor
{
public static async Task<IDisposableElement<TElement>> CreateAsync<TRazorComponent, TElement>(IServiceProvider serviceProvider, XF.Element parent = null, Action<TRazorComponent> parameterSetter = null) where TElement : class
{
var renderer = new RazorComponentRenderer(serviceProvider);
var element = await renderer.AddComponent<TRazorComponent, TElement>(parent, parameterSetter);
if (element == null)
{
throw new InvalidOperationException($"No root element of type {typeof(TElement)} can be found in razor component {typeof(TRazorComponent)}");
}
return new DisposableElement<TElement>(element, renderer);
}
public static IDisposableElement<TElement> Create<TRazorComponent, TElement>(IServiceProvider serviceProvider, XF.Element parent = null, Action<TRazorComponent> parameterSetter = null) where TElement : class
{
return CreateAsync<TRazorComponent, TElement>(serviceProvider, parent, parameterSetter).Result;
}
public static async Task<IDisposableElement<TElement>> CreateAsync<TElement>(IServiceProvider serviceProvider, Type type, XF.Element parent = null) where TElement : class
{
var renderer = new RazorComponentRenderer(serviceProvider);
var element = await renderer.AddComponent<TElement>(type, parent, null);
if (element == null)
{
throw new InvalidOperationException($"No root element of type {typeof(TElement)} can be found in razor component {type}");
}
return new DisposableElement<TElement>(element, renderer);
}
public static IDisposableElement<TElement> Create<TElement>(IServiceProvider serviceProvider, Type type, XF.Element parent = null) where TElement : class
{
return CreateAsync<TElement>(serviceProvider, type, parent).Result;
}
class RenderFragmentWrapper : ComponentBase
{
public RenderFragment ChildContent { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddContent(1, ChildContent);
}
}
public static async Task<IDisposableElement<TElement>> CreateAsync<TElement>(IServiceProvider serviceProvider, RenderFragment childContent) where TElement : class
{
var renderer = new RazorComponentRenderer(serviceProvider);
var element = await renderer.AddComponent<RenderFragmentWrapper, TElement>(null, (c)=> c.ChildContent = childContent) as TElement;
if (element == null)
{
throw new InvalidOperationException($"No root element of type {typeof(TElement)} can be found in ChildContent");
}
return new DisposableElement<TElement>(element, renderer);
}
public static IDisposableElement<TElement> Create<TElement>(IServiceProvider serviceProvider, RenderFragment childContent) where TElement : class
{
return CreateAsync<TElement>(serviceProvider, childContent).Result;
}
}
}