web-dev-qa-db-ja.com

ClientObjectプロパティがすでに取得/初期化されているかどうかを検出する適切な方法

SharePointのクライアントオブジェクトモデルを使用していて、初期化されていない、またはによって取得されていないプロパティにアクセスする場合

Context.Load(property); 
Context.ExecuteQuery();

たとえば、次のようになります。

Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException

または

コレクションは初期化されていません。リクエストされていないか、リクエストが実行されていません。

例外。

これらのプロパティがすでに初期化/取得されているかどうかを確認する前に、適切な方法はありますか?トライ/キャッチアプローチなし。私はそれが好きではありません。

例外がスローされる前に確認して処理したいと思います。

私はすでにチェックしました

IsObjectPropertyInstantiated

IsPropertyAvailable

方法ですが、実際には役に立ちません。 IsPropertyAvaiableはスカラープロパティのみをチェックし、たとえばWeb.Listsでは結果を返しません。Web.Listsは初期化されていませんが、IsObjectPropertyInstantiatedWeb.Listsに対してtrueを返します。

15
Mark

あなたの質問にはすでにある程度正しい答えが含まれていると思います。

クライアントオブジェクトプロパティがロードされているかどうかを判断するには、次のメソッドを使用できます。

テスト

テストケース1:スカラープロパティのみをロード

ctx.Load(ctx.Web, w => w.Title);
ctx.ExecuteQuery();
//Results:
ctx.Web.IsObjectPropertyInstantiated("Lists")  False
ctx.Web.IsPropertyAvailable("Title")    True

テストケース2:複合プロパティのみをロード

ctx.Load(ctx.Web, w => w.Lists);
ctx.ExecuteQuery();
//Results:
ctx.Web.IsObjectPropertyInstantiated("Lists")  True
ctx.Web.IsPropertyAvailable("Title")    False

テストケース3:スカラープロパティと複合プロパティの両方をロードする

ctx.Load(ctx.Web, w=>w.Lists,w=>w.Title);
ctx.ExecuteQuery();
//Results
ctx.Web.IsObjectPropertyInstantiated("Lists")  True
ctx.Web.IsPropertyAvailable("Title")    True


クライアントオブジェクトプロパティがロードされているかどうかを動的に判断するにはどうすればよいですか?

ClientObject.IsPropertyAvailable および ClientObject.IsObjectPropertyInstantiated メソッドは、プロパティ名が文字列値として指定されることを想定しているため、タイプミスが発生する可能性があるため、通常は次のようにします 拡張メソッド

public static class ClientObjectExtensions
{
    /// <summary>
    /// Determines whether Client Object property is loaded
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="clientObject"></param>
    /// <param name="property"></param>
    /// <returns></returns>
    public static bool IsPropertyAvailableOrInstantiated<T>(this T clientObject, Expression<Func<T, object>> property)
        where T : ClientObject
    {
        var expression = (MemberExpression)property.Body;
        var propName = expression.Member.Name;
        var isCollection = typeof(ClientObjectCollection).IsAssignableFrom(property.Body.Type);
        return isCollection ? clientObject.IsObjectPropertyInstantiated(propName) : clientObject.IsPropertyAvailable(propName);
    }
}

使用法

using (var ctx = new ClientContext(webUri))
{

     ctx.Load(ctx.Web, w => w.Lists, w => w.Title);
     ctx.ExecuteQuery();


     if (ctx.Web.IsPropertyAvailableOrInstantiated(w => w.Title))
     {
         //...
     }

     if (ctx.Web.IsPropertyAvailableOrInstantiated(w => w.Lists))
     {
         //...
     }
} 
25

Vadim Gremyachevが提供するテストは、ctx.Loadを使用するシナリオの半分しかカバーしていません。ただし、ctx.LoadQueryを使用すると、結果が変わります。

var query = from lst in ctx.Web.Lists where lst.Title == "SomeList" select lst;
var lists = ctx.LoadQuery(query);
ctx.ExecuteQuery();
ctx.Web.IsObjectPropertyInstantiated("Lists") -> True
ctx.Web.Lists.ServerObjectIsNull -> False
ctx.Web.Lists.Count -> CollectionNotInitializedException

したがって、コレクションでLoadQueryが呼び出されると、コレクションが実際に使用可能かどうかを確認できなくなります。

この場合の唯一の方法は、例外が発生したことを検出することです。

1

拡張機能を使用するというアイデアは素晴らしいですが、リストでのみ正常に機能します。拡張機能は、「オブジェクト」プロパティと「スカラー」プロパティのどちらかを選択できます。この方法では、拡張機能よりも優れていると思います。

public static bool IsPropertyAvailableOrInstantiated<T>(this T clientObject, Expression<Func<T, object>> property)
    where T : ClientObject
{
    var expression = (MemberExpression)property.Body;
    var propName = expression.Member.Name;
    var isObject = typeof(ClientObject).IsAssignableFrom(property.Body.Type); // test with ClientObject instead of ClientObjectList
    return isObject ? clientObject.IsObjectPropertyInstantiated(propName) : clientObject.IsPropertyAvailable(propName);
}

0
Jesús Pazo