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
}
}