1

WCF サービス内のリフレクションおよび DTO オブジェクトに関する他の経験とのパフォーマンスの違いを見つけることができるかどうか疑問に思っていました。Linq を使用して Entity オブジェクトから DTO オブジェクトを作成するために使用していた以下のコードがあります。

   using (dashEntities context = new dashEntities())
        {
            result = context.GetAlerts().Select(m => new AlertItemDTO()
            {

            }).ToList();

別のプログラマーは、WCF サービスを構築するときに、Reflection を使用して Generic メソッドを作成し、同じ変換を行いました。

private object TransferEntityToDTO(object dto, object entity)
    {
        Type entityType = entity.GetType();

        // Use reflection to get all properties
        foreach (PropertyInfo propertyInfo in entityType.GetProperties())
        {

            if (propertyInfo.CanRead)
            {

                List<PropertyInfo> dtoProperties = dto.GetType().GetProperties().ToList();

                foreach (PropertyInfo dtoProperty in dtoProperties)
                {

                    if (dtoProperty.Name == propertyInfo.Name)
                    {   

                        object value = propertyInfo.GetValue(entity, null);

                        if (value != null && value.ToString() != "" && value.ToString() != "1/1/0001 12:00:00 AM")
                        {
                            // This section gets the type of of the property and casts
                            // to it during runtime then sets it to the corresponding 
                            // dto value:

                            // Get current class type
                            Type currentClassType = this.GetType();

                            //Get type of property in entity object
                            Type propertyType = Type.GetType(propertyInfo.PropertyType.FullName);

                            // Get the Cast<T> method and define the type
                            MethodInfo castMethod = currentClassType.GetMethod("Cast").MakeGenericMethod(propertyType);

                            // Invoke the method giving value its true type
                            object castedObject = castMethod.Invoke(null, new object[] { value });

                            dtoProperty.SetValue(dto, value, null);

                        }
                        break;
                    }

                }

            }

        }

        return dto;
    }

    /// <summary>
    /// Used in TransferEntityToDTO to dynamically cast objects to
    /// their correct types.
    /// </summary>
    /// <typeparam name="T">Type to cast object to</typeparam>
    /// <param name="o">Object to be casted</param>
    /// <returns>Object casted to correct type</returns>
    public static T Cast<T>(object o)
    {
        return (T)o;
    }

明らかに、2 番目の手法は読みにくく、より長くなりますが、より一般的であり、複数のサービスで使用できます。

私の質問は、それを汎用にする機能は、リフレクションを使用することによるパフォーマンスへの影響を上回りますか?そうでない場合、その理由は? リフレクションが高価になる理由について、多くの混乱する記事と回答を見つけました。その一部は、取得する例外がわかっているときにすべてにジェネリック例外を使用するようなもので、まだ知らないうちに必要なオブジェクトを探す必要があるためだと思います。

誰かが私のためにこれに光を当てることができますか. ありがとう

4

3 に答える 3

3

AutoMapper、EmitMapper、ValueInjecter などの一般的なオープン ソース マッピング ライブラリのいくつかを見ると、リフレクション メソッドを使用しなくなっていることがわかります。代わりに、コンパイルされた式ツリーや IL 生成などを使用して高速化しています。アップ

明らかに、基本的なリフレクション ベースのマッパーよりも内部的に複雑になりますが (依然として非常に使いやすい)、通常どおり、速度を最適化すると複雑さが増します。

私の意見では、作成者があなたと同じように多くの質問を検討するために膨大な時間を費やしたこれらの (優れた) オープン ソース ライブラリの 1 つを使用する必要があります。

于 2012-05-17T13:07:53.427 に答える
1

これら 2 つのソリューションの主な違いは、最初のソリューションではプロジェクションを使用し、2 つ目のソリューションでは元のエンティティをマッピングすることです。元のエンティティの小さなサブセットにすぎないエンティティ (リストの dtos など) の場合、完全なエンティティではなく、投影されたプロパティのみをクエリする方が常に高速です (おそらく、ネストされたエンティティと不要なプロパティを使用して...) 、次に dto にマップされます。

両方のソリューション (射影 + 汎用ソリューション) の利点を組み合わせるには、射影式を自動的に作成し、それらをキャッシュして、元のソリューションのようにSelect(Expression<...>)呼び出し内で使用できます。したがって、すべてのマッピングは一度だけ作成され、dtos を直接取得し、必要な列のみがクエリされます。この記事とコメントをご覧ください: データ アクセス コードでの AutoMapper の使用を停止してください

AutoMapper はマッピング式を作成することもできますが、単純なプロパティのみをマップします (ソース コードから理解できる限り)。カスタム ソリューションといくつかの「式マジック」を使用すると、エンティティ フレームワークによって SQL に変換される複雑なマッピングをサポートすることもできます。

ContactName = Contact.Name,
AddressStreetAndNumber = (Address.Street + (" " + Address.Number)).Trim()

ここの githubにあるこのコードは、良い出発点です。

于 2012-05-18T08:49:40.047 に答える
0

おそらく、いくつかの軽量 ORM が役立つでしょう。たとえば、DapperPetapocoなどです。IL (Emit) を使用して、SQL クエリの結果を動的または静的オブジェクトにバインドできます。

于 2012-05-17T18:11:49.887 に答える