0

私は基本的に REST API のドキュメントを自動生成するメタデータ ジェネレーターに取り組んでいます。

これには、もちろん DTO である可能性がある要求/応答タイプの表示が含まれます。私が望むのは、オブジェクトのシリアル化された JSON (または XML) バージョンで、構造とプレースホルダー データを示しています。(シリアル化の部分は簡単ですが、最初にオブジェクトを作成するのは難しいです)。たとえば、次のオブジェクトがあるとします。

public class MyObject {
    public string Name { get; set; }
    public int Age { get; set; }
    public bool Active { get; set; }
}

私はいくつかの関数を呼び出すことができるようにしたい:

var obj = GetDefaultValue(typeof(MyObject));

と同等のものを取得します。

new MyObject { Name = string.Empty, Age = 0, Active = false };
// or in other words:  new MyObject { Name = default(string), Age = default(int), Active = default(bool) };

これを開始する基本的なコードがいくつかあります。

    /// <summary>
    /// Class to create a default value for a specified type.
    /// </summary>
    public abstract class DefaultValueGenerator
    {
        private DefaultValueGenerator() { }

        /// <summary>
        /// Creates a new default instance of type T.
        /// Requires that T has a parameter-less constructor, or can be created using <code>default(T)</code>
        /// </summary>
        /// <param name="T"></param>
        /// <returns></returns>
        public static object GetDefaultValue(Type T)
        {
            try
            {
                return System.Activator.CreateInstance(T, true);
                //TODO: if array type, also create a single item of that type
            }
            catch (Exception activatorException)
            {
                try
                {
                    // from http://stackoverflow.com/a/2490267/7913
                    var defaultGeneratorType = typeof(DefaultGenerator<>).MakeGenericType(T);

                    return defaultGeneratorType.InvokeMember(
                      "GetDefault",
                      BindingFlags.Static |
                      BindingFlags.Public |
                      BindingFlags.InvokeMethod,
                      null, null, new object[0]);
                }
                catch //(Exception defaultGeneratorException)
                {
                    throw new MissingMethodException(string.Format("No parameterless constructor defined for model {0}", T.Name), activatorException);
                }

            }

        }

        // from http://stackoverflow.com/a/2490267/7913
        private class DefaultGenerator<T>
        {
            public static T GetDefault()
            {
                return default(T);
            }
        }


    }

したがって、これを使用して次のように呼び出すことができます。

var obj = DefaultValueGenerator.GetDefaultValue(typeof(MyObject));

この実装の問題点の 1 つは、それを呼び出すDefaultValueGenerator.GetDefaultValue(typeof(string))と、キャッチした例外がスローされ、キーワードactivatorExceptionが使用されることです。default私は例外に頼っているので、ただ醜い..もっと良い方法はありますか?


2 番目の問題は配列/コレクションです。例:DefaultValueGenerator.GetDefaultValue(typeof(List<MyObject>))要素が 0 のリストを作成し、それを JSON にシリアル化します[]-- ドキュメントに関してはあまり役に立ちません。これで1つの要素を生成したいと思います。


3 番目の問題は、ネストされた型です。たとえば、私が持っている場合:

public class MyContainerObject {
    public MyObject OtherObject { get; set; }
    public int SomeValue { get; set; }
}

これに相当するものを生成したいと思います:

var obj = new MyContainerObject { 
    OtherObject = new MyObject { Name = string.Empty, Age = 0, Active = false },
    SomeValue = 0,
}

しかし実際には、OtherObject を null 値として生成します。


すでにこれを行っているコード/ライブラリを知っている人はいますか? それ以外の場合、これを達成する方法と、私が指摘したいくつかの落とし穴を避けるためのヒントはありますか? これをより簡単に解決する別の方法はありますか?

組み込みの基本型 (string、int、guid など) だけでなく、より複雑なオブジェクトでも、パラメーターのないコンストラクターがある限り、これが機能することを望みます (私はその制限で問題ありません。いずれにせよ、使用される型は POCO/DTO でなければなりません)。

4

1 に答える 1

0

完全な書き換え

DefaultGenerator のソース コードがあるようです。TryMakeGenericType オーバーロードを作成して、醜い try...catch ブロックを排除できます。これにより、コードがよりエレガントになります。例外がスローされているという事実を排除するわけではありませんが、非表示にします。

リストに関して、リストに格納されているアイテムのタイプを判別する方法はありませんか? これを取得したら、コードをレンダリングしてその型のメンバーを初期化するコードを挿入するのは比較的簡単なことだと思います。

ネストされた型は、リストで遭遇したのと同じ問題のようです。実際のところ、1 つの問題を解決すると、もう 1 つの問題の解決策がすぐに明らかになると思います。ただし、すべてのソースを表示しないと、わかりにくいです。

同意します。すでにこれを行っているライブラリがあればとてもいいと思います。ここで、XML API のようなものを見つけたいと思います。適切な代替手段が見つかるまで、短期的には、現在持っているものを拡張する必要があるでしょう。

于 2012-01-27T21:29:57.020 に答える