2
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 5 years have passed since last update.

匿名型objectを特定クラスのインスタンスに変換する

Posted at

はじめに

匿名型のオブジェクトをクラスのインスタンスにしたいとき、ありますよね。

こんなソースコードは嫌だ

例えば、こんなソースがあったとします。

using System;

namespace tekitou
{
    class Program
    {
        public class DataClass
        {
            public string strText { get; set; }
            public int numHoge { get; set; }

            public override string ToString()
            {
                return $"{strText}, {numHoge}";
            }
        }

        static object NanrakaFunction()
        {
            return new { strText = "hogehoge", numHoge = 323 };
        }

        static void Main(string[] args)
        {
            var obj = NanrakaFunction();
            var fuga = (dynamic)obj as DataClass;
            if (fuga == null)
            {
                Console.WriteLine("fuga is null");
            }
            else
            {
                Console.WriteLine(fuga);
            }
        }
    }
}
  • NanrakaFunctionが staticなのヤバい」
  • NanrakaFunctionの 型、なんで DataClass じゃないの?」

などなど、static object NanrakaFunction の設計が激やばなのは認めます。
ただ、上記のソースコードほどではないとはいえ、こういう設計にならざるを得ないこともあるのではないでしょうか。

実行結果

このソースコード、実行すると当然

fuga is null

が返されます。
ではどうするか?それが今日の本題です。

解決方法

これ、バッドプラクティスな可能性がだいぶありますので、
使用する際は自己責任で。

わたし、気づきました。

Console.WriteLine(JsonSerializer.Serialize(obj));

{"strText":"hogehoge","numHoge":323}

実装

static void Main(string[] args)
{
    var obj = NanrakaFunction();
    var strJson = JsonSerializer.Serialize(obj);
    var fuga = JsonSerializer.Deserialize<DataClass>(strJson);

    if (fuga == null)
    {
        Console.WriteLine("fuga is null");
    }
    else
    {
        Console.WriteLine(fuga);
    }
}

バッドプラクティス臭がプンプンしますね!
要は一旦JSONでシリアライズできる形ならJSON文字列化してしまって、
あとでデシリアライズすればいいのです。

型チェックもちゃんとできる

例えば、 numHoge に float型の数値をいれてみたところ・・

例外が発生しました: CLR/System.Text.Json.JsonException
型 'System.Text.Json.JsonException' のハンドルされていない例外が System.Text.Json.dll で発生しました
 内部例外が見つかりました。詳細については、変数ウィンドウの $exception を参照してください。
 最も内側の例外 	 System.FormatException : Either the JSON value is not in a supported format, or is out of bounds for an Int32.
   場所 System.Text.Json.Utf8JsonReader.GetInt32()
   場所 System.Text.Json.Serialization.Converters.JsonConverterInt32.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
   場所 System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(ReadStack& state, Utf8JsonReader& reader)
   場所 System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
   場所 System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)

いいぞ。

ちゃんとデシリアライズ時の例外をチェックすれば、型がちゃんとできてるかどうかもわかります。

終わりに

とまぁ、今回は NanrakaFunction というかたちで、関数で定義しましたが、
引数でやってくる場合もあるわけです。(objectで受けるな、というのはあるが)

とりあえずの処置として使えるかな、ということで記事にしてみました。
変換を自前で書くほどデンジャラスなこともないと思うので、公式のライブラリに委ねてみましょう、ということでした。

2
0
0

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
2
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?