C# 这是一个有趣的问题:)

C# 这是一个有趣的问题:),c#,linq,facebook,C#,Linq,Facebook,编辑:变异是一条路吗? 在您的评论中看到,本地用户类型实际上是实体框架中的实体类型,因此可能不适合采取这种做法。使其不可变几乎是不可能的,而且我怀疑该类型的大多数用途都会预期突变 如果是这样的话,可能需要更改界面以使其更清晰。与其返回IEnumerable(这在某种程度上意味着投影),您可能需要同时更改签名和名称,这样您就可以得到如下结果: public sealed class FacebookMerger : IUserMerger { public void MergeInform

编辑:变异是一条路吗?

在您的评论中看到,本地用户类型实际上是实体框架中的实体类型,因此可能不适合采取这种做法。使其不可变几乎是不可能的,而且我怀疑该类型的大多数用途都会预期突变

如果是这样的话,可能需要更改界面以使其更清晰。与其返回
IEnumerable
(这在某种程度上意味着投影),您可能需要同时更改签名和名称,这样您就可以得到如下结果:

public sealed class FacebookMerger : IUserMerger
{
    public void MergeInformation(IEnumerable<User> users)
    {
        var facebookUsers = GetFacebookUsers(users);
        var uidDictionary = facebookUsers.ToDictionary(fb => fb.uid);

        foreach (var user in users)
        {
            FacebookUser fb;
            if (uidDictionary.TryGetValue(user.FacebookUid, out fb)
            {
                user.Avatar = fb.pic_square;
            }
        }
    }

    private Facebook.user[] GetFacebookUsers(IEnumerable<User> users)
    {
        var uids = (from u in users
                    where u.FacebookUid != null
                    select u.FacebookUid.Value).Distinct().ToList();

        // return facebook users for uids using WCF
    }
}
公共密封类FaceBookMerge:IUSERMerge
{
公共信息(IEnumerable用户)
{
var facebookUsers=GetFacebookUsers(用户);
var uidDictionary=facebookUsers.ToDictionary(fb=>fb.uid);
foreach(用户中的var用户)
{
facebook用户fb;
if(uidDictionary.TryGetValue(user.FacebookUid,out-fb)
{
user.Avatar=fb.pic_square;
}
}
}
私有Facebook.user[]GetFacebookUsers(IEnumerable用户)
{
var uids=(来自用户中的u)
其中u.facebookud!=null
选择u.FacebookUid.Value).Distinct().ToList();
//使用WCF向facebook用户返回UID
}
}

同样,这不再是一个特别的“LINQ-y”解决方案(在主操作中)——但这是合理的,因为你不是真正的“查询”;你是“更新”。

Jon,这太棒了+1,我喜欢你的工作。我想我理解分组,我可能会选择该选项。如果我使用分组方法,我必须调用.Concat吗(NullFacebookUsers)?另外,我的本地用户是一个EF对象,你知道一个好的克隆方法吗?不,分组位处理“非facebook用户”,因为它不匹配任何用户,这就是为什么我们使用DefaultIfEmpty().First()。不,我不知道克隆EF实体。恐怕:(@bendewey:考虑到这个问题的EF性质,我在我的答案(底部)中添加了一点额外的内容。哎呀,我刚刚看到你为什么问.Concat(…)为分组操作设置了位。很抱歉意外地添加了此项!现已修复…+1感谢您的回答这很有帮助,Jon在LINQ中的分组技术更符合我的要求。
public IEnumerable<User> MapFrom(IEnumerable<User> users)
{
  // didn't have a way to check if u.FacebookUid == null
  return from u in users
    join f in GetFacebookUsers(users) on u.FacebookUid equals f.uid
    select AppendAvatar(u, f);
}

public void AppendAvatar(User u, Facebook.user f)
{
  if (f == null)
    return u;
  u.FacebookAvatar = f.pic_square;
  return u;
}
public IEnumerable<User> MapFrom(IEnumerable<User> users)
{
  // had to get the user from the facebook service for each single user,
  // would rather use a single http request.
  return from u in users
    let f = GetFacebookUser(user.FacebookUid)
    select AppendAvatar(u, f);
}
public class FacebookMapper : IMapper
{
    public IEnumerable<User> MapFacebookAvatars(IEnumerable<User> users)
    {
        var usersByID =
            users.Where(u => u.FacebookUid.HasValue)
                 .ToDictionary(u => u.FacebookUid.Value);

        var facebookUsersByID =
            GetFacebookUsers(usersByID.Keys).ToDictionary(f => f.uid);

        foreach(var id in usersByID.Keys.Intersect(facebookUsersByID.Keys))
            usersByID[id].FacebookAvatar = facebookUsersByID[id].pic_sqare;

        return users;
    }

    public Facebook.user[] GetFacebookUsers(IEnumerable<int> uids)
    {
       // return facebook users for uids using WCF
    }
}
public IEnumerable<User> MapFrom(IEnumerable<User> users)
public User WithAvatar(Image avatar)
{
    // Whatever you need to create a clone of this user
    User clone = new User(this.Name, this.Age, etc);
    clone.FacebookAvatar = avatar;
    return clone;
}
// Adjust for however the user should actually be constructed.
private static readonly FacebookUser NullFacebookUser = new FacebookUser(null);
private static readonly IEnumerable<FacebookUser> NullFacebookUsers =
    Enumerable.Repeat(new FacebookUser(null), 1);
public IEnumerable<User> MapFrom(IEnumerable<User> users)
{
    var facebookUsers = GetFacebookUsers(users).Concat(NullFacebookUsers);
    return from user in users
           join facebookUser in facebookUsers on
                user.FacebookUid equals facebookUser.uid
           select user.WithAvatar(facebookUser.Avatar);
}
public sealed class FacebookMapper : IMapper
{
    private static readonly IEnumerable<FacebookUser> NullFacebookUsers =
        Enumerable.Repeat(new FacebookUser(null), 1);

    public IEnumerable<User> MapFrom(IEnumerable<User> users)
    {
        var facebookUsers = GetFacebookUsers(users).Concat(NullFacebookUsers);
        return from user in users
               join facebookUser in facebookUsers on
                    user.FacebookUid equals facebookUser.uid
               select user.WithAvatar(facebookUser.pic_square);
    }

    private Facebook.user[] GetFacebookUsers(IEnumerable<User> users)
    {
        var uids = (from u in users
                    where u.FacebookUid != null
                    select u.FacebookUid.Value).ToList();

        // return facebook users for uids using WCF
    }
}
public IEnumerable<User> MapFrom(IEnumerable<User> users)
{
    var facebookUsers = GetFacebookUsers(users);
    return from user in users
           join facebookUser in facebookUsers on
                user.FacebookUid equals facebookUser.uid
                into matchingUsers
           let firstMatch = matchingUsers.DefaultIfEmpty().First()
           select firstMatch == null ? user : user.WithAvatar(firstMatch.pic_square);
}
// "Source" sequence is just our local users
from user in users
// Perform a group join - the "matchingUsers" range variable will
// now be a sequence of FacebookUsers with the right UID. This could be empty.
join facebookUser in facebookUsers on
     user.FacebookUid equals facebookUser.uid
     into matchingUsers
// Convert an empty sequence into a single null entry, and then take the first
// element - i.e. the first matching FacebookUser or null
let firstMatch = matchingUsers.DefaultIfEmpty().First()
// If we've not got a match, return the original user.
// Otherwise return a new copy with the appropriate avatar
select firstMatch == null ? user : user.WithAvatar(firstMatch.pic_square);
public IEnumerable<User> MapFrom(IEnumerable<User> users)
{
    var facebookUsers = GetFacebookUsers(users);
    var uidDictionary = facebookUsers.ToDictionary(fb => fb.uid);

    foreach (var user in users)
    {
        FacebookUser fb;
        if (uidDictionary.TryGetValue(user.FacebookUid, out fb)
        {
            yield return user.WithAvatar(fb.pic_square);
        }
        else
        {
            yield return user;
        }
    }
}
    private Facebook.user[] GetFacebookUsers(IEnumerable<User> users)
    {
        var uids = (from u in users
                    where u.FacebookUid != null
                    select u.FacebookUid.Value).Distinct().ToList();

        // return facebook users for uids using WCF
    }
public sealed class FacebookMerger : IUserMerger
{
    public void MergeInformation(IEnumerable<User> users)
    {
        var facebookUsers = GetFacebookUsers(users);
        var uidDictionary = facebookUsers.ToDictionary(fb => fb.uid);

        foreach (var user in users)
        {
            FacebookUser fb;
            if (uidDictionary.TryGetValue(user.FacebookUid, out fb)
            {
                user.Avatar = fb.pic_square;
            }
        }
    }

    private Facebook.user[] GetFacebookUsers(IEnumerable<User> users)
    {
        var uids = (from u in users
                    where u.FacebookUid != null
                    select u.FacebookUid.Value).Distinct().ToList();

        // return facebook users for uids using WCF
    }
}