次の方法で共有


LINQ don't stink

Recently, I had to write a test case that posed an interesting problem. 

The product that I am working, Identity Lifecycle Manager "2" uses the concept of sets.  Sets are defined by XPath filter expressions.  When a user submits a request to create, read, update or delete a resource, then that resource, as well as associated resources, may transition into or out of any number of sets. 

We have a Request type for representing user's requests, and when we determine the set transitions that will result from a request, we add the information about those set transitions to the Request object.  Each set transition is represented by a piece of XML that looks roughly like this:

<SetTransition>

<ResourceIdentifier>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</ResourceIdentifier>

<SetIdentifier>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</SetIdentifier>

<Join>1</Join>

<Leave>0</Leave>

</SetTransition>

A Request object has a SetTransition property of the ReadOnlyCollection<string> type, with each string in the collection being an XML representation of a set transition.  We don't have to reason about the set transitions programmatically any further in our C# code, so it suffices that they are exposed as strings of XML, rather than as strongly-typed objects. 

Now, in my test case, I create a Request, dip it into the part of our request processor that figures out the set transitions, and then decide whether it calculated the set transitions correctly.  It should be apparent that deciding whether the set transitions were calculated correctly is a matter of querying a .NET collection of strings of XML, to determine whether that XML contains the correct data. 

As a general solution for querying data of any sort, LINQ seemed to be the appropriate tool for the job, and that did turn out to be the case.  Specifically, it was possible for me to craft my test so that I could ask, in a single statement, whether the transitions of two particular resources into two particular sets was detected:

var count =

(

from document

in

(

from item

in request.SetTransitions

select XDocument.Parse(item)

)

where

(

(

//There is a transition to or from the set.

(

from element

in document.Descendants()

where

(

(

(

string.Equals(element.Name.ToString(), "SetIdentifier", StringComparison.Ordinal))

&&

(

string.Equals(element.Value, setIdentifier.GetGuid().ToString(), StringComparison.Ordinal))

)

)

select element

).Count() == 1

)

&&

(

//The transition is to the set.

(

(

from element

in document.Descendants()

where

(

(

(

string.Equals(element.Name.ToString(), "Join", StringComparison.Ordinal))

&&

(

string.Equals(element.Value, bool.TrueString, StringComparison.OrdinalIgnoreCase))

)

)

select element

).Count() == 1

)

&&

(

(

from element

in document.Descendants()

where

(

(

(

string.Equals(element.Name.ToString(), "Leave", StringComparison.Ordinal))

&&

(

string.Equals(element.Value, bool.TrueString, StringComparison.OrdinalIgnoreCase))

)

)

select element

).Count() == 0

)

)

&&

(

//The senior manager and the president are transitioning.

(

from element

in document.Descendants()

where

(

(

(

string.Equals(element.Name.ToString(), "ResourceIdentifier", StringComparison.Ordinal))

&&

(

(

string.Equals(element.Value, seniorManagerIdentifier.GetGuid().ToString(), StringComparison.Ordinal))

||

(

string.Equals(element.Value, presidentIdentifier.GetGuid().ToString(), StringComparison.Ordinal))

)

)

)

select element

).Count() == 1

)

)

select document

).Count();

if ((int)count == 2)

{

FilterEvaluationTest.WriteColoredLine(ConsoleColor.Green,

"Recursive transitions are anticipated.");

}

else

{

return;

}

So, there you have it: a single C# LINQ statement that does the equivalent of looping through an array of strings of XML, parsing each of them, looking for particular values.

Comments

  • Anonymous
    May 20, 2008
    Dear McMurtry, I'am an edtior of Turingbook(www.turingbook.com) of China. If I incommode you, please forgive me. Turingbook have introduced into the great book of Windows Communication Foundation Unleashed and translated it into Chinese which will be published soon, I'm the responsible editor  of this book . We are designing the cover of this book and we need some information of you and other authors, we will place it on the backcover(If the cover is ok, it will be like the one in the affix). The information of you as follows: 1.Introduction of you, details: 1)the IT technology  you mastery(good at); 2)your work experience, such as you are working at Microsoft; 3)the achievement or prize you have got; 4)except Windows Communication Foundation Unleashed, did you wrote any other books? 5)do you have some article for magazine, for example... 6)the community you have joined and you principalship and so on 2.the nationality of you 3.a photo of you Thank you very much, we need your help, ohterwise the Chinese version can not be published. Waiting for you message! Contact me: E-mail: linux1689@gmail.com MSN: erwa_yang@hotmail.com