2

私のプラグイン コードでは、事前にバインドされたエンティティ ( crmsvcutilで生成) を使用しています。私のコードでは、MemberExpression を使用してプロパティの名前を取得しています。たとえば、プラグインを開始したユーザーのフル ネームが必要な場合は、次のようにします。

SystemUser pluginExecutedBy = new SystemUser();
pluginExecutedBy = Common.RetrieveEntity(service
                                        , SystemUser.EntityLogicalName
                                        , new ColumnSet(new string[] {Common.GetPropertyName(() => pluginExecutedBy.FullName)})
                                        , localContext.PluginExecutionContext.InitiatingUserId).ToEntity<SystemUser>();

GetPropertyName のコードは次のとおりです。

    public static string GetPropertyName<T>(Expression<Func<T>> expression)
    {
        MemberExpression body = (MemberExpression)expression.Body;
        return body.Member.Name.ToLower();
    }

RetrieveEntity のコードは次のとおりです。

public static Entity RetrieveEntity(IOrganizationService xrmService, string entityName, ColumnSet columns, Guid entityId)
        {
            return (Entity)xrmService.Retrieve(entityName, entityId, columns);
        }

私のソリューション アーキテクトのコメント:

上記のようなコードを書く代わりに、このように書いてみませんか (フィールドの名前をハードコーディングするか、構造体を使用します)。

SystemUser pluginExecutedBy = null;
pluginExecutedBy = Common.RetrieveEntity(service
                                        , SystemUser.EntityLogicalName
                                        , new ColumnSet(new string[] {"fullname"})
                                        , localContext.PluginExecutionContext.InitiatingUserId).ToEntity<SystemUser>();

理由:

  1. あなたのコードは、それが必要になる前に不必要にオブジェクトを作成します ( newGetProperty メソッドで使用するために RetrieveEntity の前にキーワードを使用してオブジェクトをインスタンス化するため)、これはプログラミングの悪い習慣です。私のコードでは、newキーワードを使用したことはありませんが、単にキャストしてキャストしても新しいオブジェクトは作成されません。現在、私は C# や .NET の専門家ではありませんが、さまざまなことを読んで試してみるのが好きです。そこで、Microsoft.Xrm.Sdk.dll を調べたところ、Sdk 内の ToEntity が実際にキーワードを使用して新しいエンティティを作成したことがわかりましたnew
  2. Common.Retrieve が null を返す場合、コードに不必要にメモリが割り当てられているため、パフォーマンスの問題が発生しますが、私の場合はそうではありませんか? C# のようなマネージ言語は、私にとっては「メモリを管理する」ものではないでしょうか?

質問

  1. 私のコードは正しく書かれていませんか? もしそうなら、なぜですか?それがより良い場合 - それはなぜですか?(私はそれがはるかにきれいだと信じています。フィールド名が変更されたとしても、事前にバインドされたクラス ファイルが再生成される限り、コードを書き直す必要はありません)

  2. キャストが新しいオブジェクトを作成しないことに同意しますが、私のコードは不必要にオブジェクトを作成しますか?

  3. コードを記述するためのより良い方法 (まったく異なる第 3 の方法) はありますか?

注: GetPropertyName を使用することをお勧めしました。彼はコード全体で属性名をハードコーディングしていたため、事前にバインドされたエンティティを使用しない別のプロジェクトでは、属性名に構造体を使用しました-以下のようなものです。私はこれを CRM 2011 での新しい仕事の 3 週間前に行いましたが、後でMemberExpressionの魔法を発見しました。彼はプラグインで使用しているエンティティごとに大量の cs ファイルを作成していましたが、プラグインで GetPropertyName メソッドを使用するだけで必要なすべてのフィールドを取得できるので、これを行う必要はないと彼に伝えました。このコードレビューのコメントを促した. 通常、彼はコード レビューを行いません。

public class ClientName
{
    public struct EntityNameA
    {
        public const string LogicalName = "new_EntityNameA";
        public struct Attributes
        {
            public const string Name = "new_name";
            public const string Status = "new_status";
        }
    }
}

PS: それとも、質問や分析に費やす時間は価値がないのでしょうか?

4

2 に答える 2

2

GetPropertyName非常に賢い解決策ですが、私は好きではありません。それは完全に読みやすさに関係しています。私にとっては、何が起こっているのかを理解するのがはるかに簡単です: new ColumnSet(new string[] {"fullname"})

しかし、それはかなり個人的な好みですが、自分のためにコードを書くだけでなく、チームのためにコードを書いていることを覚えておくことが重要です。

側面として、ハードコードされた文字列はおそらく実行時のパフォーマンスが向上します。私は通常、すべての値をハードコードします。CRM のエンティティ モデルが変更された場合は、変更を加えるために再訪する必要があります。その状況では、アーリーバウンドとレイトバウンドに違いはありません。

この関数の意味がわかりません。

public static Entity RetrieveEntity(IOrganizationService xrmService, string entityName, ColumnSet columns, Guid entityId)
{
    return (Entity)xrmService.Retrieve(entityName, entityId, columns);
}

何もしません (すでにそのタイプのものをキャストすることを除いて)。

1.あなたのコードは、それを必要とする前に不必要にオブジェクトを作成します(GetPropertyメソッドで使用するためにRetrieveEntityの前に新しいキーワードでオブジェクトをインスタンス化するため)、これはプログラミングの悪い習慣です。私のコードでは、 new キーワードを使用したことはありませんが、単にキャストしてキャストしても新しいオブジェクトは作成されません。

これは次のことを指していると思います。SystemUser pluginExecutedBy = new SystemUser();ここで彼/彼女のポイントを見ることができますが、この場合new SystemUser()はあまり効果がありませんが、インスタンス化していたオブジェクトがリソースを集中的に使用する (ファイルをロードする、DB 接続を開く) 場合、「無駄」なことをしている可能性があります。この場合、変更SystemUser pluginExecutedBy = null;によって実際に大幅なパフォーマンスの向上が得られたとしたら、私は驚くでしょう。

2.Common.Retrieve が null を返す場合、コードに不必要にメモリが割り当てられているため、パフォーマンスの問題が発生します。

それがパフォーマンスの問題を引き起こしたとしたら、私は驚くだろう. とにかく、Guidoが指摘しているように、その関数はどのような場合でもnullを返さない.

全体として、このコードについて変更が必要だと強く感じている点はほとんどありません。しかし、常により良いものになる可能性があり、議論する価値があります (コード レビューのポイントなど)。

個人的には、ハードコーディングされた属性名を使用し、何もしないので Common.RetrieveEntity 関数をダンプします。

pluginExecutedBy = service.Retrieve(SystemUser.EntityLogicalName, localContext.PluginExecutionContext.InitiatingUserId, new ColumnSet(new String[] {"fullname"} ));
于 2013-04-30T12:52:04.727 に答える