メインコンテンツまでスキップ

メタモデルに依存しないモデル操作を行う

メタモデルに設定できるタグを用いることによって、メタモデルのクラス名やフィールド名に依存しないモデル操作が可能です。

タグでフィールドの値を取得する

メタモデルのクラスやフィールドにセットしたタグ付き値を用いてフィールドを取得するには、IModelオブジェクトのGetFieldValuesByFieldTagメソッドを用います。タグがセットされているすべてのフィールドの値が戻ってきますので、コレクションで操作をするか、LINQのFirstOrDefaultメソッドで最初の1つ目を取得します。

public void GetFieldByTag(ICommandContext c, ICommandParams p)
{
IModel model = c.App.Workspace.CurrentModel;
var value = model.GetFieldValuesByFieldTag("SomeTag").FirstOrDefault();

if ( value is IModel)
{
// モデルの場合はIModelでキャストします
var valueModel = value as IModel;

c.App.Output.WriteLine("sample", $"Model: {valueModel.Name}");
}
else
{
// それ以外は文字列に変換します
c.App.Output.WriteLine("sample", $"Value: {value.ToString()}");
}
}

拡張メソッド

タグアクセスは次のような拡張メソッドのクラスを定義しておくと便利です。

IModelExtension.cs

/// <summary>
/// IModelに関する拡張メソッド群です
/// </summary>
public static class IModelExtensions
{
/// <summary>
/// 指定フィールドの値をモデルとして取得します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="field">フィールド名。</param>
/// <returns>取得したモデル。取得できない場合はnullです。</returns>
public static IModel GetModel(this IModel self, string field)
{
return self.GetField(field) as IModel;
}

/// <summary>
/// フィールドのタグでモデルを取得します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTag">フィールドのタグ名。</param>
/// <returns>取得したモデル。取得できない場合はnullです。</returns>
public static IModel GetModelByFieldTag(this IModel self, string fieldTag)
{
return self.GetFieldValuesByFieldTag(fieldTag).OfType<IModel>().FirstOrDefault();
}

/// <summary>
/// フィールドのタグでモデルのコレクションを取得します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTag">フィールドのタグ。</param>
/// <returns>取得したモデルコレクション。取得できない場合は空のコレクションです。</returns>
public static IEnumerable<IModel> GetModelsByFieldTag(this IModel self, string fieldTag)
{
var ret = self.GetFieldValuesByFieldTag(fieldTag).OfType<IModel>();
if (ret == null)
{
return Enumerable.Empty<IModel>();
}

return ret;
}

/// <summary>
/// モデルの指定タグのフィールド情報を取得します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTag">指定のタグ。</param>
/// <returns>フィールド情報。取得できない場合はnullです。</returns>
public static IField GetFieldByFieldTag(this IModel self, string fieldTag)
{
return self.Metaclass.GetFieldsByTag(fieldTag).FirstOrDefault();
}

/// <summary>
/// 指定タグのフィールド名を取得します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTag">指定のタグ。</param>
/// <returns>フィールド名。取得できない場合はnullです。</returns>
public static string GetFieldNameByFieldTag(this IModel self, string fieldTag)
{
return self.GetFieldByFieldTag(fieldTag)?.Name;
}

/// <summary>
/// 指定タグのフィールドがメタモデルに定義されているモデルかを確認します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTag">指定のタグ。</param>
/// <returns>定義されている場合はtrue、それ以外はfalseです。</returns>
public static bool HasFieldTag(this IModel self, string fieldTag)
{
return self.Metaclass.GetFieldsByTag(fieldTag).Any();
}
/// <summary>
/// 指定タグのフィールドがメタモデルに定義されているモデルかを確認します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTags">指定のタグ。カンマ区切りで指定します。</param>
/// <returns>すべて定義されている場合はtrue、それ以外はfalseです。</returns>
public static bool HasFieldTags(this IModel self, string fieldTags)
{
var fieldTagList = fieldTags.Split(',');
return HasFieldTags(self, fieldTagList);
}

/// <summary>
/// 指定タグのフィールドがメタモデルに定義されているモデルかを確認します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTagList">指定のタグのコレクション。</param>
/// <returns>すべて定義されている場合はtrue、それ以外はfalseです。</returns>
public static bool HasFieldTags(this IModel self, IEnumerable<string> fieldTagList)
{
foreach (var fieldTag in fieldTagList)
{
if (!self.Metaclass.GetFieldsByTag(fieldTag).Any())
{
return false;
}
}
return true;
}

/// <summary>
/// フィールドのタグでフィールド値を取得します。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTag">フィールドのタグ。</param>
/// <returns>フィールド値。取得できない場合はnullです。</returns>
public static string GetFieldValueStringByTag(this IModel self, string fieldTag)
{
var ret = self.GetFieldValuesByFieldTag(fieldTag).FirstOrDefault();
return ret as string;
}

/// <summary>
/// フィールドのタグでフィールド値を設定します。
/// 該当フィールドが見つからない場合は何もしません。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTag">フィールドのタグ。</param>
/// <param name="value">設定値。</param>
public static void SetFieldByTag(this IModel self, string fieldTag, object value)
{
var field = GetFieldByFieldTag(self, fieldTag);
if (field == null)
{
return;
}
self.SetField(field, value);
}

/// <summary>
/// フィールドのタグで新しいモデルを追加します。
/// 該当フィールドが見つからない場合は例外をスローします。
/// </summary>
/// <param name="self">対象モデル。</param>
/// <param name="fieldTag">フィールドのタグ。</param>
/// <param name="className">追加するモデルのクラス名。未指定の場合はフィールドの型のクラスを使用します。</param>
public static IModel AddNewModelByFieldTag(this IModel self, string fieldTag, string className = null)
{
var field = self.GetFieldByFieldTag(fieldTag);
if (field == null)
{
throw new ArgumentException($"{fieldTag}のフィールドが見つかりませんでした。");
}

if (className == null)
{
className = field.TypeClass.Name;
}

return self.AddNewModel(field.Name, className);
}
}