Guest User

Untitled

a guest
Dec 18th, 2017
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.83 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using System.Linq.Expressions;
  4. using System.Reflection;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using MongoDB.Bson;
  8. using MongoDB.Bson.Serialization.Attributes;
  9. using MongoDB.Driver;
  10. using MongoDB.Driver.Core.Bindings;
  11. using MongoDB.Driver.Core.Operations;
  12.  
  13. namespace XXX
  14. {
  15. public static class MongoExtensions
  16. {
  17. public static void Save<T>(this IMongoCollection<T> collection, T item)
  18. {
  19. if (item == null)
  20. throw new ArgumentNullException(nameof(item));
  21.  
  22. if (MongoSaveCommandHelper<T>.ShouldInsert(item))
  23. {
  24. collection.InsertOne(item);
  25. }
  26. else
  27. {
  28. var expression = MongoSaveCommandHelper<T>.GetIdEqualityExpression(item);
  29. collection.ReplaceOne(expression, item);
  30. }
  31. }
  32.  
  33. private static class MongoSaveCommandHelper<T>
  34. {
  35. private static readonly Expression<Func<T, bool>> IdIsEqualToDefaultExpression;
  36. private static readonly Func<T, object> GetId;
  37. public static Func<T, bool> ShouldInsert { get; }
  38.  
  39. static MongoSaveCommandHelper()
  40. {
  41. var members = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
  42. var idProperty = members.SingleOrDefault(x => x.IsDefined(typeof(BsonIdAttribute)))
  43. ?? members.FirstOrDefault(m => m.Name.Equals("id", StringComparison.OrdinalIgnoreCase));
  44. if (idProperty == null)
  45. throw new InvalidOperationException("Id property has not found");
  46.  
  47. var idPropertyType = idProperty.PropertyType;
  48. var parameter = Expression.Parameter(typeof(T));
  49. var idPropertyAccess = Expression.MakeMemberAccess(parameter, idProperty);
  50. var getIdFuncExpression = Expression.Lambda<Func<T, object>>(Expression.Convert(idPropertyAccess, typeof(object)), parameter);
  51.  
  52. GetId = getIdFuncExpression.Compile();
  53. IdIsEqualToDefaultExpression = Expression.Lambda<Func<T, bool>>(Expression.Equal(idPropertyAccess, Expression.Default(idPropertyType)), getIdFuncExpression.Parameters);
  54. ShouldInsert = IdIsEqualToDefaultExpression.Compile();
  55. }
  56.  
  57. public static Expression<Func<T, bool>> GetIdEqualityExpression(T item) =>
  58. (Expression<Func<T, bool>>)new IdConstantVisitor(GetId(item)).Visit(IdIsEqualToDefaultExpression);
  59. }
  60.  
  61. private class IdConstantVisitor : ExpressionVisitor
  62. {
  63. private readonly object _value;
  64. public IdConstantVisitor(object value) => _value = value;
  65. protected override Expression VisitDefault(DefaultExpression node) => Expression.Constant(_value, node.Type);
  66. }
  67. }
  68. }
Add Comment
Please, Sign In to add comment