问题
In c#, I'm simply grabbing "/me/friends" from the FB api,
private void FacebookFriends()
{
FB.API("/me/friends", HttpMethod.GET, FBAPIFriendsCallback);
}
private void FBAPIFriendsCallback(FBResult response)
{
// (error handling here - no problem)
// ugly code...
var dict = Json.Deserialize(response.Text)
as Dictionary<string,object>;
var friendList = new List<object>();
friendList = (List<object>)(dict["data"]);
int _friendCount = friendList.Count;
// ugly code...
// (example shows getting one item, would loop through all)
string id = getDataValueForKey(
(Dictionary<string,object>)(friendList[0]), "id" );
string name = getDataValueForKey(
(Dictionary<string,object>)(friendList[0]), "name" );
}
Notice the very, very ugly code -- what's the more elegant way to write this? Cheers
In fact, per swazza's comment below, here's the full code passage:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Parse;
using System;
using Facebook;
using System.Threading.Tasks;
using System.IO;
using System.Linq;
using Facebook.MiniJSON;
public class ParseLinkOps : MonoBehaviour
{
...
public void GetFriendsFromFBThenMatch()
{
FB.API("/me/friends", HttpMethod.GET, _cbFriends);
// FB calls at
// https://developers.facebook.com/docs/unity/reference/current
}
private void _cbFriends(FBResult response)
{
// goal: given the json result from the cloud,
// create a List<string> containing only the FacebookID "id" numbers
if ( ! String.IsNullOrEmpty(response.Error) )
{ // .. error handling .. return; }
var dict = Json.Deserialize(response.Text)
as Dictionary<string,object>;
var friendList = new List<object>();
friendList = (List<object>)(dict["data"]);
int _friendCount = friendList.Count;
Debug.Log("Found friends on FB, _friendCount ... " +_friendCount);
// so, convert that complex array of FB objects,
// to simply an array of "id" strings
// use very ugly code but assume someone on SO knows better later :-)
List<string> friendIDsFromFB = new List<string>();
for ( int k=0; k<_friendCount; ++k)
{
string friendFBID =
getDataValueForKey( (Dictionary<string,object>)(friendList[k]), "id");
string friendName =
getDataValueForKey( (Dictionary<string,object>)(friendList[k]), "name");
Debug.Log( k +"/" +_friendCount +" " +friendFBID +" " +friendName);
friendIDsFromFB.Add( friendFBID );
}
// we're done, the list is in friendIDsFromFB
StartCoroutine( _match( friendIDsFromFB ) );
}
...
}
回答1:
How about using linq extensions?
var dict = new Dictionary<string, object>();
var friend = dict
.Where(s => s.Key.Equals("data"))
.Select(s => new { Id = s.Key, Name = s.Value })
.First();
var friendId = friend.Id;
var friendName = friend.Name;
Here is a linq extension to iterate over an enumerable and perform an action on each element -
public static void Execute<TSource>(this IEnumerable<TSource> source, Action<TSource> actionToExecute)
{
if (source.Count() > 0)
{
foreach (var item in source)
{
actionToExecute(item);
}
}
}
EDIT: So I understand that you are using this in Unity game engine. Its been ages since I worked on Unity. Glad to know they have support for Linq now. So here is the code that I wrote that get the friendIds. There is some code that is specific to ASP.Net but the linq part should work anywhere -
// Use ASP.Net's Javascript serializer to desrialize the json response received from
// call to graph.facebook.com/me/friends
var jsSerializer = new JavaScriptSerializer();
var jsonString = "{ \"data\": [ { \"name\": \"name1\", \"id\": \"id1\" }, { \"name\": \"name2\", \"id\": \"id2\" } ] }";
// Deserialize the json to type - Dictionary<string, object>
var dict = jsSerializer.Deserialize(jsonString, typeof(Dictionary<string, object>)) as Dictionary<string, object>;
/*Code upto here is specific to ASP.Net - At this point, be it ASP.Net or Unity, we have a dictionary that contains a key "data" which again contains a dictionaries of name value pairs*/
// The code from below is Linq and should work on Unity as well.
var friendIds = (dict["data"] as ArrayList) // Convert the "data" key of the dictionary into its underlying type (which is an ArrayList in this case)
.Cast<Dictionary<string, object>>() // ArrayList is not generic. Cast it to a generic enumerable where each element is of type Dictionary<string, object>
.Select(s =>
{
// Each element in the cast enumerable is of type dictionary.
// Each dictionary has two keys - "id" and "name" that correspond to the id and name properties
// of the json response received when calling graph.facebook.com/me/friends.
// check - https://developers.facebook.com/tools/explorer/145634995501895/?method=GET&path=me%2Ffriends&version=v2.0
// Because we only want Ids, fetch the value corresponding to the "id" key
object id = null;
if (s.TryGetValue("id", out id))
{
return id.ToString();
}
return string.Empty;
});
I put in verbose comments to make that code a bit self explanatory. If you remove the comments, it makes for concise code. However, this is less performant than a plain for loop.
来源:https://stackoverflow.com/questions/23431622/best-c-sharp-syntax-idiom-reading-array-of-friends-from-facebook