0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Blazorアプリケーションをリファクタリングしようとして失敗しているお話

Posted at

概要

  • コードをリファクタリングしてみたら意図通りに動作できなかった記録 (現在進行形)

宣伝

C#とBlazorでホロライブファン向けの動画ビューワー『ホロビューワー』を開発しました

何した

  • 『ホロビューワー』のコードをリファクタリングしてた。
  • 下記のように同じようなコードが何度も現れるのをなんとかしたかった。

リリース時 (コードの一部を抜粋)
画面分割モードに応じて、GridとGridCellを使用してアプリケーションのUIを生成する処理

@switch (ApplicationScreenMode.CurrentScreenMode)
{
    case ScreenMode.Single:
        <Grid HorizontalOptions="LayoutOptions.FillAndExpand" VerticalOptions="LayoutOptions.FillAndExpand">
            <StackLayout>
                <WebViewToolbar @ref="WebViewToolbar1" />
                <BlazorWebView @ref="BlazorWebView1" VerticalOptions="LayoutOptions.FillAndExpand">
                    <HoloViewer.WebUI.App />
                </BlazorWebView>
            </StackLayout>
        </Grid>
        break;

    case ScreenMode.SplitHorizontal2:
        <Grid RowDefinitions="*, *" HorizontalOptions="LayoutOptions.FillAndExpand" VerticalOptions="LayoutOptions.FillAndExpand">
            <GridCell Row="0">
                <StackLayout>
                    <WebViewToolbar @ref="WebViewToolbar1" />
                    <BlazorWebView @ref="BlazorWebView1" VerticalOptions="LayoutOptions.FillAndExpand">
                        <HoloViewer.WebUI.App />
                    </BlazorWebView>
                </StackLayout>
            </GridCell>
            <GridCell Row="1">
                <StackLayout>
                    <WebViewToolbar @ref="WebViewToolbar2" />
                    <BlazorWebView @ref="BlazorWebView2" VerticalOptions="LayoutOptions.FillAndExpand">
                        <HoloViewer.WebUI.App />
                    </BlazorWebView>
                </StackLayout>
            </GridCell>
        </Grid>
        break;
// 以下同じようなコードが続いていた

GridCellの設定はまとめられることに気がつく。 (最初と同じ辺りの処理を抜粋)

case ScreenMode.Single:
    <Grid HorizontalOptions="LayoutOptions.FillAndExpand" VerticalOptions="LayoutOptions.FillAndExpand">
        <StackLayout>
            <WebViewToolbar @ref="WebViewToolbars" />
            <BlazorWebView @ref="BlazorWebViews" VerticalOptions="LayoutOptions.FillAndExpand">
                <HoloViewer.WebUI.App />
            </BlazorWebView>
        </StackLayout>
    </Grid>
    break;

case ScreenMode.SplitHorizontal2:
    <Grid RowDefinitions="*, *" HorizontalOptions="LayoutOptions.FillAndExpand" VerticalOptions="LayoutOptions.FillAndExpand">
        @for (int i = 0; i < 2; i++)
        {
            <GridCell Row="@i">
                <StackLayout>
                    <WebViewToolbar @ref="WebViewToolbars" />
                    <BlazorWebView @ref="BlazorWebViews" VerticalOptions="LayoutOptions.FillAndExpand">
                        <HoloViewer.WebUI.App />
                    </BlazorWebView>
                </StackLayout>
            </GridCell>
        }
    </Grid>
    break;

ちょっとマシになった。 (ここまでは正常に動作していた)

Gridの設定もバラバラに行うのではなく一箇所にまとめられることに気がつく。(同じ辺りのコードを抜粋。ここから失敗コース)

<Grid @ref="grid" RowDefinitions="@GridSettings[ApplicationScreenMode.CurrentScreenMode].rowDefinitions" ColumnDefinitions="@GridSettings[ApplicationScreenMode.CurrentScreenMode].columnDefinitions" HorizontalOptions="LayoutOptions.FillAndExpand" VerticalOptions="LayoutOptions.FillAndExpand">
    @for (int i = 0; i < GridSettings[ApplicationScreenMode.CurrentScreenMode].cellCount; i++)
    {
        <GridCell Row="@GridSettings[ApplicationScreenMode.CurrentScreenMode].rowIndies[i]" Column="@GridSettings[ApplicationScreenMode.CurrentScreenMode].columnIndies[i]" ColumnSpan="@GridSettings[ApplicationScreenMode.CurrentScreenMode].columnSpanCounts[i]">
            <StackLayout>
                <WebViewToolbar @ref="WebViewToolbars" />
                <BlazorWebView @ref="BlazorWebViews" VerticalOptions="LayoutOptions.FillAndExpand">
                    <HoloViewer.WebUI.App />
                </BlazorWebView>
            </StackLayout>
        </GridCell>
    }
</Grid>

@code
{
    public class GridSetting
    {
        public readonly string rowDefinitions;
        public readonly string columnDefinitions;
        public readonly int cellCount;
        public readonly int[] rowIndies;
        public readonly int[] columnIndies;
        public readonly int[] columnSpanCounts;

        public GridSetting (string rowDefinitions, string columnDefinitions, int cellCount, int[] rowIndies, int[] columnIndies, int[] columnSpanCounts)
        {
            this.rowDefinitions = rowDefinitions;
            this.columnDefinitions = columnDefinitions;
            this.cellCount = cellCount;
            this.rowIndies = rowIndies;
            this.columnIndies = columnIndies;
            this.columnSpanCounts = columnSpanCounts;
        }
    }

    public static readonly Dictionary<ScreenMode, GridSetting> GridSettings = new Dictionary<ScreenMode, GridSetting>()
    {
        { ScreenMode.Single, new GridSetting("*", "*", 1, new int[]{ 0 }, new int[]{ 0 }, new int[]{ 1 }) },

        { ScreenMode.SplitHorizontal2, new GridSetting("*, *", "*", 2, new int[]{ 0, 1 }, new int[]{ 0, 0 }, new int[]{ 1, 1 }) },
        { ScreenMode.SplitVertical2, new GridSetting("*", "*, *", 2, new int[]{ 0, 0 }, new int[]{ 0, 1 }, new int[]{ 1, 1 }) },

        { ScreenMode.SplitHorizontal3, new GridSetting("*, *, *", "*", 3, new int[]{ 0, 1, 2 }, new int[]{ 0, 0, 0 }, new int[]{ 1, 1, 1 }) },
        { ScreenMode.SplitVertical3, new GridSetting("*", "*, *, *", 3, new int[]{ 0, 0, 0 }, new int[]{ 0, 1, 2 }, new int[]{ 1, 1, 1 }) },
        { ScreenMode.SplitCustom3_1, new GridSetting("*, *", "*, *", 3, new int[]{ 0, 1, 1 }, new int[]{ 0, 0, 1 }, new int[]{ 2, 1, 1 }) },
        { ScreenMode.SplitCustom3_2, new GridSetting("*, *", "*, *", 3, new int[]{ 0, 0, 1 }, new int[]{ 0, 1, 0 }, new int[]{ 1, 1, 2 }) },

        { ScreenMode.SplitHorizontal4, new GridSetting("*, *, *, *", "*", 4, new int[]{ 0, 1, 2, 3 }, new int[]{ 0, 0, 0, 0 }, new int[]{ 1, 1, 1, 1 }) },
        { ScreenMode.SplitVertical4, new GridSetting("*", "*, *, * ,*", 4, new int[]{ 0, 0, 0, 0 }, new int[]{ 0, 1, 2, 3 }, new int[]{ 1, 1, 1, 1 }) },
        { ScreenMode.SplitCustom4, new GridSetting("*, *", "*, *", 4, new int[]{ 0, 0, 1, 1 }, new int[]{ 0, 1, 0, 1 }, new int[]{ 1, 1, 1, 1 }) },
    };

いざビルドして動かしてみると、以前と動作が違う。
例えば画面分割モードを横2分割の後に縦2分割を選択すると、以下の画像のように直前の変更が残ってしまうようになった。

  • 変更前 (縦に2分割して、2つのページが横に並んでいる正常な状態)
    HoloViewer_Before.png

  • 変更後 (縦に2分割したいのに、直前の横2分割操作の影響を受けて、2*2の4分割モードになってしまっている)
    HoloViewer_After.png

やってみたけど効果がなかったこと

  • Gridプロパティを覗いてみると、RowDefinitionsとColumnDefinitionsが反映されているのにChildrenが変更されずに残ったままになっていたので、Grid.NativeControl.Children.Clear()でコントロールを削除してみた。
    • 画面分割モードを変更してもページが再生成されず、ページが表示されなかった。
    • ページが表示されないとダメなのでこの方法はボツ
  • Xamarin関連のパッケージをプレビュー版も含めてアップデートした。
    • 2020/11/28時点での最新版にアップデートしても変化がなかった。
    • こちらも効果がなかったのでボツ

結論

  • コードをまとめるのは諦める。
  • 一旦コードはこのままにしてフレームワークなどの更新を待ってみる。
  • Blazorへの理解を深めて対応できる問題なのかもう少し調査したい。
0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?