げんさん日記

プログラミングで気付いた事等を書きます。

プロパティの属性を取得する。

2022年06月30日 09時40分43秒 | C#
プロパティに設定してある指定の属性を取得する。

var attribute = (DespriptionAttribute)propertyInfo.GetCustomeAttribute(typeof(DespriptionAttribute), true).SingleOrDefault();
if (attribute ==null) return;

上記はDespription属性を取得して存在をチェックしてます。

全モデルのベースを作成する。(IDisposable)

2021年05月20日 15時00分10秒 | C#
メモリのリークを最小限にする為、デストラクタを正しく定義し、「BaseModel」を作成して行きます。

クラスの名前をBaseModelにしてIDisposableを継承します。

解放済みを確認するフラグを用意します。
public abstract class BaseModel : IDisposable
{
  protected bool IsDisposed { get; set; }
}

次にデストラクタを定義しDisposeをfaiseで呼び出します。
~BaseModel()
{
  this.Dispose(false);
}

PublicのDisposeを定義します。
public void Dispose()
{
  // DisposeをTrueで呼び出す。
  this.Dispose(true);
  // 自分を解放する。
  GC.SuppressFinalize(this);
}

管理外のオブジェクトを解放する為、ProtectedのDisposeを定義します。
protected virtual void Dispose(bool disposing = true)
{
  // 解放済みなら何もしない
  if (this.IsDisposed == true) return;

  // 管理外のオブジェクトを解放する。
  if (disposing == true)
  {
  }
  this.IsDisposed = true;
}

継承先のモデル例
public Class TestModel : BaseModel
{
  // Disposeをオーバーライド
  protected override void Dispose(bool disposing = true)
  {
   // 解放済みなら何もしない
   if (this.IsDisposed == true) return;

   // 管理外オブジェクトの解放
   if (disposing == true)
   {
    // 自クラスのオブジェクト&イベントの解放
   }

   // ベースの解放を呼び出す。
   base.Dispose(disposing);
  }
}

ジェネリックを使用したモデルの保存・リストアを行います。

2019年11月06日 11時06分00秒 | C#
データモデル内にジェネリックが存在する場合に通常のSerialize及びDeserializeではエラーになり正しく処理できない為、データを一度メモリに出力し、その内容をシリアライズする事でジェネリックデータの保存を可能にします。その方法を下記に記します。

オブジェクトを保存する。
public void Save<T>(T saveObject, string fileName)
{
  // データをシリアライズして保存します。
  using (var memoryStream = new MemoryStream())
  {
    var binaryFormatter = new BinaryFormatter();
    binaryFormatter.Serialize(memoryStream, saveObject);
    System.IO.File.WriteAllBytes(fileName, memoryStream.ToArray());
    binaryFormatter = null;
  }
}

オブジェクトをリストアする。
public T Restore(string fileName)
{
  var binaryFormatter = new BinaryFormatter();

  try
  {
    using (var memoryStream = new MemoryStream(System.IO.File.ReadAllBytes(fileName)))
    {
      memoryStream.Seek(0, SeekOrigin.Begin);
      var obj = binaryFormatter.Deserialize(memoryStream);
      return (T)obj;
    }

  }
  finally
  {
    binaryFormatter = null;
  }
}


配列の要素を全て削除する。(メモリリーク対策)

2019年11月06日 10時13分18秒 | C#
配列要素を削除する場合にremoveとかclearを使用すると配列からは削除されるがメモリ上からは削除されない場合があります。その場合にメモリリークすることがあります。その対策としてDispose属性が存在する場合にはDisposeメソッドを実行し確実にメモリからの解放を行うものとする。その方法を下記に記します。

配列要素を全て削除する拡張クラスを作成します。
public static void RemoveAll<T>(this ICollection<T> values)
{
  // nullの時、処理を終了する。
  if (values == null)
  {
    return;
  }

  // 要素の数分繰り返します。
  foreach (var value in values)
  {
    // IDisposable型の時、Disposeを行います。
    IDisposable disp = value as IDisposable;
    if (disp != null)
    {
      disp.Dispose();
      disp = null;
    }
  }

  // 要素をクリアします。
  values.Clear();
}

使用例
public void OnClick()
{
  this.List.RemoveAll();
}
上記で配列情報がクリアされます。

Enumの内容をコンボボックス用のデータとして取得する。

2019年11月06日 09時49分12秒 | C#
enumに設定してある内容をコンボボックスのデータとして取得する方法を下記に記します。

enumの定義を下記のようにします。Descriptionに表示する内容を定義します。
public enum EncodeType
{
  [Description("shift_jis")]
  ShiftJis = 0,
  [Description("utf-8")]
  UTF8 = 1,
}

Enum値を取得する拡張クラスを作成します。
public static int Value(this Enum value)
{
  // Fieldを取得します。
  var fi = value.GetType().GetField(value.ToString());

  // Fieldから値を取得し返します。
  return (int)fi.GetValue(null);
}

Enum値に対応する名称を取得する拡張クラスを作成します。
public static string Name(this Enum value)
{
  // 指定されたEumのFieldを取得します。
  var fi = value.GetType().GetField(value.ToString());
  if (fi == null)
  {
    // 取得できなかった時、NULLを返します。
    return null;
  }

  // DescriptionAttributeを取得します。
  var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
  if (attributes != null && attributes.Length > 0)
  {
    // DescriptionAttributeが存在する時、DescriptionAttributeの内容を返します。
    return attributes[0].Description;
  }
  else
  {
    // DescriptionAttributeが存在しない時、値に対応する名称を返します。
    return value.ToString();
  }
}

コンボボックス用データを取得する拡張クラスを作成します。
public static ICollection GetComboData<T>(this T value)
{
  // Enumの値リストを取得します。
  var fields = value.GetType().GetFields();
  var enmName = value.GetType().Name;

  // 値リストからコンボデータを作成します。
  var datas = fields.ToList().Where(w => w.FieldType.Name == enmName).Select(s => new Models.ComboBoxModel()
   {
     Value = ((int)s.GetValue(null)).ToString(),
     Name = Name((Enum)s.GetValue(null)),
   }).ToList();

  // 作成したコンボデータを返します。
  return datas;
}
※Models.ComboBoxModelはValue とName を持つモデルです。

使用例
public void OnClick()
{
  var comboData = (default(EncodeType)).GetComboData();
}
上記でEnumの値を全て取得できますし、enumの内容が変更されても対応がenumの変更のみで終わる為、保守性が上がります。