くうと徒然なるままに

モバイルアプリを作りながらバックエンドも作っています。

「ConnpassReportGenerator」V2.0 Beta をリリースしました。階層化したタグで 要素を指定できるようにしました。

Connpass Report Generator とは

Connpass のイベントページから報告書などを半自動生成したい!みたいなのをかなえるツールです。

新機能

階層化したタグを指定するようになった

使い方

{URL.MeetupURL}

実行結果

https://lh3.googleusercontent.com/-FJkllbKWkn8/WWXIpH6CAZI/AAAAAAAAK4Q/T7a1PZ0MZ1kIfwK5Ev3AnHMgG-e613UzACHMYCw/s0/2017-07-12_15-58-43.png

実装方法

小規模な修正で済むかと思っていたが、想定以上に工数がかかってしまった。

やったこと

用意するデータの整理などの細かな作業もしました。しかし、一番大きいのは以下の部分かなと思っています。

テンプレートエンジンの改造

今までは、データ保持しているクラスと同じ名前のタグが存在しないかなー?って検索してました。今後データの種類を増やすことを視野にいれ、それでは、不必要な部分が多そうだったので、 タグの名前(パス)からデータを保持しているクラスからプロパティ、クラスを引き当てるように仕様変更しました。

public class ArticleTemplateEngine : IArticleTemplateEngine
    {
        public string ReplaceArticleData<T>(string templateText, T data)
        {
            if (string.IsNullOrWhiteSpace(templateText) || data == null) return "";
            var Tags = TagStringCollection(templateText);

            foreach (var tag in Tags)
            {
                var PropertyValue = GetPropertyFromIdentify(tag, data);
                if (PropertyValue == null) continue;
                templateText = templateText.Replace($"{tag}", PropertyValue);
            };
            return templateText;
        }

        private string GetPropertyFromIdentify<T>(string TagName, T data)
        {
            var dataType = (object)data;

            var PathList = IdentifyList(TagName);
            var ValuePropertyName = PathList.Last();
            PathList.RemoveAt(PathList.Count - 1);

            foreach (var path in PathList)
            {
                dataType = dataType.GetType().GetProperty(path)?.GetValue(data);
            }

            return dataType.GetType().GetProperty(ValuePropertyName)?.GetValue(dataType) as string;
        }

        private List<string> TagStringCollection(string templateText)
        {
            var collection = new Regex(@"\{(.+?)\}").Matches(templateText);
            var Tags = new List<string>();
            for (int i = 0; i < collection.Count; i++)
            {
                Tags.Add(collection[i].Value);
            }
            return Tags;
        }

        private List<string> IdentifyList(string TagName) => TagName.Split('.').Select(s => s.Replace(".", "").Replace("{", "").Replace("}", "")).Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
        
    }

今後導入したい機能

  • タグの入力補完
  • タグ一覧のドキュメントの自動生成