Implementation of new generic interfaces

--- SimplePersistence/SimplePersistence.UoW.EF/EFAsyncRepository.cs
+++ SimplePersistence/SimplePersistence.UoW.EF/EFAsyncRepository.cs
@@ -388,4 +388,1139 @@

         #endregion
     }
+
+    /// <summary>
+    /// Implementation of an <see cref="IAsyncRepository{TEntity,TId}"/> for the Entity Framework,
+    /// exposing only async operations
+    /// </summary>
+    /// <typeparam name="TEntity">The entity type</typeparam>
+    /// <typeparam name="TId01">The entity id first type</typeparam>
+    /// <typeparam name="TId02">The entity id second type</typeparam>
+    public class EFAsyncRepository<TEntity, TId01, TId02> : IAsyncRepository<TEntity, TId01, TId02>
+        where TEntity : class
+        where TId01 : IEquatable<TId01>
+        where TId02 : IEquatable<TId02>
+    {
+        private readonly Func<TEntity, TId01, TId02, bool> _filterById;
+        private readonly DbSet<TEntity> _dbSet;
+        private readonly DbContext _dbContext;
+
+        /// <summary>
+        /// The Entity Framework database context
+        /// </summary>
+        protected DbContext DbContext
+        {
+            get { return _dbContext; }
+        }
+
+        /// <summary>
+        /// The <see cref="IDbSet{TEntity}"/> of this repository entity
+        /// </summary>
+        protected DbSet<TEntity> DbSet
+        {
+            get { return _dbSet; }
+        }
+
+        /// <summary>
+        /// Creates a new async repository
+        /// </summary>
+        /// <param name="dbContext">The database context</param>
+        /// <param name="filterById">The filter by the entity if expression</param>
+        /// <exception cref="ArgumentNullException"></exception>
+        public EFAsyncRepository(DbContext dbContext, Func<TEntity, TId01, TId02, bool> filterById)
+        {
+            if (dbContext == null) throw new ArgumentNullException("dbContext");
+            if (filterById == null) throw new ArgumentNullException("filterById");
+
+            _filterById = filterById;
+            _dbContext = dbContext;
+            _dbSet = dbContext.Set<TEntity>();
+        }
+
+        #region Query
+
+        /// <summary>
+        /// Gets an <see cref="System.Linq.IQueryable{T}"/> for this repository entities
+        /// </summary>
+        /// <returns>The <see cref="System.Linq.IQueryable{T}"/> object</returns>
+        public IQueryable<TEntity> Query()
+        {
+            return DbSet;
+        }
+
+        /// <summary>
+        /// Gets an <see cref="IQueryable{TEntity}"/> for this repository entities
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <returns>The <see cref="IQueryable{TEntity}"/> object</returns>
+        public IQueryable<TEntity> QueryById(TId01 id01, TId02 id02)
+        {
+            return Query().Where(e => _filterById(e, id01, id02));
+        }
+
+        /// <summary>
+        /// Gets an <see cref="System.Linq.IQueryable{T}"/> for this repository entities
+        /// that will also fetch, on execution, all the entity navigation properties
+        /// </summary>
+        /// <param name="propertiesToFetch">The navigation properties to also fetch on query execution</param>
+        /// <returns>The <see cref="System.Linq.IQueryable{T}"/> object</returns>
+        /// <exception cref="ArgumentNullException"></exception>
+        public IQueryable<TEntity> QueryFetching(params Expression<Func<TEntity, object>>[] propertiesToFetch)
+        {
+            if (propertiesToFetch == null) throw new ArgumentNullException("propertiesToFetch");
+            return
+                propertiesToFetch
+                    .Aggregate<Expression<Func<TEntity, object>>, IQueryable<TEntity>>(
+                        DbSet, (current, expression) => current.Include(expression));
+        }
+
+        #endregion
+
+        #region GetById
+
+        /// <summary>
+        /// Gets an entity by its unique identifier from this repository asynchronously
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> that will fetch the entity</returns>
+        public async Task<TEntity> GetByIdAsync(TId01 id01, TId02 id02)
+        {
+            return await DbSet.FindAsync(id01, id02);
+        }
+
+        /// <summary>
+        /// Gets an entity by its unique identifier from this repository asynchronously
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> that will fetch the entity</returns>
+        public async Task<TEntity> GetByIdAsync(TId01 id01, TId02 id02, CancellationToken ct)
+        {
+            return await DbSet.FindAsync(ct, id01, id02);
+        }
+
+        #endregion
+
+        #region Add
+
+        /// <summary>
+        /// Adds the entity to the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to add</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> AddAsync(TEntity entity)
+        {
+            return await AddAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Adds the entity to the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to add</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> AddAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Add(entity));
+        }
+
+        /// <summary>
+        /// Adds a range of entities to the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entity to add</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> AddAsync(IEnumerable<TEntity> entities)
+        {
+            return await AddAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Adds a range of entities to the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entity to add</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> AddAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Add(entities));
+        }
+
+        #endregion
+
+        #region Update
+
+        /// <summary>
+        /// Updates the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to update</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> UpdateAsync(TEntity entity)
+        {
+            return await UpdateAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Updates the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to update</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> UpdateAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Update(entity));
+        }
+
+        /// <summary>
+        /// Updates a range of entities in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to update</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> UpdateAsync(IEnumerable<TEntity> entities)
+        {
+            return await UpdateAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Updates a range of entities in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to update</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> UpdateAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Update(entities));
+        }
+
+        #endregion
+
+        #region Delete
+
+        /// <summary>
+        /// Deletes the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to delete</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> DeleteAsync(TEntity entity)
+        {
+            return await DeleteAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Deletes the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to delete</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> DeleteAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Delete(entity));
+        }
+
+        /// <summary>
+        /// Deletes a range of entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to delete</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> DeleteAsync(IEnumerable<TEntity> entities)
+        {
+            return await DeleteAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Deletes a range of entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to delete</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> DeleteAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Delete(entities));
+        }
+
+        #endregion
+
+        #region Total
+
+        /// <summary>
+        /// Gets the total entities in the repository asynchronously
+        /// </summary>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the total</returns>
+        public async Task<long> TotalAsync()
+        {
+            return await DbSet.LongCountAsync();
+        }
+
+        /// <summary>
+        /// Gets the total entities in the repository asynchronously
+        /// </summary>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the total</returns>
+        public async Task<long> TotalAsync(CancellationToken ct)
+        {
+            return await DbSet.LongCountAsync(ct);
+        }
+
+        #endregion
+
+        #region Exists
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <returns>True if entity exists</returns>
+        public bool Exists(TId01 id01, TId02 id02)
+        {
+            return QueryById(id01, id02).Any();
+        }
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <returns>True if entity exists</returns>
+        public async Task<bool> ExistsAsync(TId01 id01, TId02 id02)
+        {
+            return await QueryById(id01, id02).AnyAsync();
+        }
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <param name="ct">The <see cref="CancellationToken"/> for the returned task</param>
+        /// <returns>True if entity exists</returns>
+        public async Task<bool> ExistsAsync(TId01 id01, TId02 id02, CancellationToken ct)
+        {
+            return await QueryById(id01, id02).AnyAsync(ct);
+        }
+
+        #endregion
+
+        #region Private
+
+        private TEntity Add(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State == EntityState.Detached)
+                return DbSet.Add(entity);
+
+            dbEntityEntry.State = EntityState.Added;
+            return dbEntityEntry.Entity;
+        }
+
+        private IEnumerable<TEntity> Add(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return DbSet.AddRange(entities);
+        }
+
+        private TEntity Update(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State == EntityState.Detached)
+                DbSet.Attach(entity);
+            if (dbEntityEntry.State != EntityState.Added && dbEntityEntry.State != EntityState.Deleted)
+                dbEntityEntry.State = EntityState.Modified;
+
+            return dbEntityEntry.Entity;
+        }
+
+        private IEnumerable<TEntity> Update(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return entities.Select(Update).ToArray();
+        }
+
+        private TEntity Delete(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State != EntityState.Deleted)
+            {
+                dbEntityEntry.State = EntityState.Deleted;
+                return dbEntityEntry.Entity;
+            }
+
+            DbSet.Attach(entity);
+            DbSet.Remove(entity);
+
+            return entity;
+        }
+
+        private IEnumerable<TEntity> Delete(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return entities.Select(Delete).ToArray();
+        }
+
+        #endregion
+    }
+
+    /// <summary>
+    /// Implementation of an <see cref="IAsyncRepository{TEntity,TId}"/> for the Entity Framework,
+    /// exposing only async operations
+    /// </summary>
+    /// <typeparam name="TEntity">The entity type</typeparam>
+    /// <typeparam name="TId01">The entity id first type</typeparam>
+    /// <typeparam name="TId02">The entity id second type</typeparam>
+    /// <typeparam name="TId03">The entity id third type</typeparam>
+    public class EFAsyncRepository<TEntity, TId01, TId02, TId03> : IAsyncRepository<TEntity, TId01, TId02, TId03>
+        where TEntity : class
+        where TId01 : IEquatable<TId01>
+        where TId02 : IEquatable<TId02>
+        where TId03 : IEquatable<TId03>
+    {
+        private readonly Func<TEntity, TId01, TId02, TId03, bool> _filterById;
+        private readonly DbSet<TEntity> _dbSet;
+        private readonly DbContext _dbContext;
+
+        /// <summary>
+        /// The Entity Framework database context
+        /// </summary>
+        protected DbContext DbContext
+        {
+            get { return _dbContext; }
+        }
+
+        /// <summary>
+        /// The <see cref="IDbSet{TEntity}"/> of this repository entity
+        /// </summary>
+        protected DbSet<TEntity> DbSet
+        {
+            get { return _dbSet; }
+        }
+
+        /// <summary>
+        /// Creates a new async repository
+        /// </summary>
+        /// <param name="dbContext">The database context</param>
+        /// <param name="filterById">The filter by the entity if expression</param>
+        /// <exception cref="ArgumentNullException"></exception>
+        public EFAsyncRepository(DbContext dbContext, Func<TEntity, TId01, TId02, TId03, bool> filterById)
+        {
+            if (dbContext == null) throw new ArgumentNullException("dbContext");
+            if (filterById == null) throw new ArgumentNullException("filterById");
+
+            _filterById = filterById;
+            _dbContext = dbContext;
+            _dbSet = dbContext.Set<TEntity>();
+        }
+
+        #region Query
+
+        /// <summary>
+        /// Gets an <see cref="System.Linq.IQueryable{T}"/> for this repository entities
+        /// </summary>
+        /// <returns>The <see cref="System.Linq.IQueryable{T}"/> object</returns>
+        public IQueryable<TEntity> Query()
+        {
+            return DbSet;
+        }
+
+        /// <summary>
+        /// Gets an <see cref="IQueryable{TEntity}"/> for this repository entities
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <param name="id03">The entity third identifier value</param>
+        /// <returns>The <see cref="IQueryable{TEntity}"/> object</returns>
+        public IQueryable<TEntity> QueryById(TId01 id01, TId02 id02, TId03 id03)
+        {
+            return Query().Where(e => _filterById(e, id01, id02, id03));
+        }
+
+        /// <summary>
+        /// Gets an <see cref="System.Linq.IQueryable{T}"/> for this repository entities
+        /// that will also fetch, on execution, all the entity navigation properties
+        /// </summary>
+        /// <param name="propertiesToFetch">The navigation properties to also fetch on query execution</param>
+        /// <returns>The <see cref="System.Linq.IQueryable{T}"/> object</returns>
+        /// <exception cref="ArgumentNullException"></exception>
+        public IQueryable<TEntity> QueryFetching(params Expression<Func<TEntity, object>>[] propertiesToFetch)
+        {
+            if (propertiesToFetch == null) throw new ArgumentNullException("propertiesToFetch");
+            return
+                propertiesToFetch
+                    .Aggregate<Expression<Func<TEntity, object>>, IQueryable<TEntity>>(
+                        DbSet, (current, expression) => current.Include(expression));
+        }
+
+        #endregion
+
+        #region GetById
+
+        /// <summary>
+        /// Gets an entity by its unique identifier from this repository asynchronously
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <param name="id03">The entity third identifier value</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> that will fetch the entity</returns>
+        public async Task<TEntity> GetByIdAsync(TId01 id01, TId02 id02, TId03 id03)
+        {
+            return await DbSet.FindAsync(id01, id02, id03);
+        }
+
+        /// <summary>
+        /// Gets an entity by its unique identifier from this repository asynchronously
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <param name="id03">The entity third identifier value</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> that will fetch the entity</returns>
+        public async Task<TEntity> GetByIdAsync(TId01 id01, TId02 id02, TId03 id03, CancellationToken ct)
+        {
+            return await DbSet.FindAsync(ct, id01, id02, id03);
+        }
+
+        #endregion
+
+        #region Add
+
+        /// <summary>
+        /// Adds the entity to the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to add</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> AddAsync(TEntity entity)
+        {
+            return await AddAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Adds the entity to the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to add</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> AddAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Add(entity));
+        }
+
+        /// <summary>
+        /// Adds a range of entities to the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entity to add</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> AddAsync(IEnumerable<TEntity> entities)
+        {
+            return await AddAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Adds a range of entities to the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entity to add</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> AddAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Add(entities));
+        }
+
+        #endregion
+
+        #region Update
+
+        /// <summary>
+        /// Updates the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to update</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> UpdateAsync(TEntity entity)
+        {
+            return await UpdateAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Updates the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to update</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> UpdateAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Update(entity));
+        }
+
+        /// <summary>
+        /// Updates a range of entities in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to update</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> UpdateAsync(IEnumerable<TEntity> entities)
+        {
+            return await UpdateAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Updates a range of entities in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to update</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> UpdateAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Update(entities));
+        }
+
+        #endregion
+
+        #region Delete
+
+        /// <summary>
+        /// Deletes the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to delete</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> DeleteAsync(TEntity entity)
+        {
+            return await DeleteAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Deletes the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to delete</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> DeleteAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Delete(entity));
+        }
+
+        /// <summary>
+        /// Deletes a range of entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to delete</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> DeleteAsync(IEnumerable<TEntity> entities)
+        {
+            return await DeleteAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Deletes a range of entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to delete</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> DeleteAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Delete(entities));
+        }
+
+        #endregion
+
+        #region Total
+
+        /// <summary>
+        /// Gets the total entities in the repository asynchronously
+        /// </summary>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the total</returns>
+        public async Task<long> TotalAsync()
+        {
+            return await DbSet.LongCountAsync();
+        }
+
+        /// <summary>
+        /// Gets the total entities in the repository asynchronously
+        /// </summary>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the total</returns>
+        public async Task<long> TotalAsync(CancellationToken ct)
+        {
+            return await DbSet.LongCountAsync(ct);
+        }
+
+        #endregion
+
+        #region Exists
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <param name="id03">The entity third identifier value</param>
+        /// <returns>True if entity exists</returns>
+        public bool Exists(TId01 id01, TId02 id02, TId03 id03)
+        {
+            return QueryById(id01, id02, id03).Any();
+        }
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <param name="id03">The entity third identifier value</param>
+        /// <returns>True if entity exists</returns>
+        public async Task<bool> ExistsAsync(TId01 id01, TId02 id02, TId03 id03)
+        {
+            return await QueryById(id01, id02, id03).AnyAsync();
+        }
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="id01">The entity first unique identifier value</param>
+        /// <param name="id02">The entity second unique identifier value</param>
+        /// <param name="id03">The entity third identifier value</param>
+        /// <param name="ct">The <see cref="CancellationToken"/> for the returned task</param>
+        /// <returns>True if entity exists</returns>
+        public async Task<bool> ExistsAsync(TId01 id01, TId02 id02, TId03 id03, CancellationToken ct)
+        {
+            return await QueryById(id01, id02, id03).AnyAsync(ct);
+        }
+
+        #endregion
+
+        #region Private
+
+        private TEntity Add(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State == EntityState.Detached)
+                return DbSet.Add(entity);
+
+            dbEntityEntry.State = EntityState.Added;
+            return dbEntityEntry.Entity;
+        }
+
+        private IEnumerable<TEntity> Add(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return DbSet.AddRange(entities);
+        }
+
+        private TEntity Update(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State == EntityState.Detached)
+                DbSet.Attach(entity);
+            if (dbEntityEntry.State != EntityState.Added && dbEntityEntry.State != EntityState.Deleted)
+                dbEntityEntry.State = EntityState.Modified;
+
+            return dbEntityEntry.Entity;
+        }
+
+        private IEnumerable<TEntity> Update(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return entities.Select(Update).ToArray();
+        }
+
+        private TEntity Delete(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State != EntityState.Deleted)
+            {
+                dbEntityEntry.State = EntityState.Deleted;
+                return dbEntityEntry.Entity;
+            }
+
+            DbSet.Attach(entity);
+            DbSet.Remove(entity);
+
+            return entity;
+        }
+
+        private IEnumerable<TEntity> Delete(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return entities.Select(Delete).ToArray();
+        }
+
+        #endregion
+    }
+
+    /// <summary>
+    /// Implementation of an <see cref="IAsyncRepository{TEntity}"/> for the Entity Framework,
+    /// exposing only async operations
+    /// </summary>
+    /// <typeparam name="TEntity">The entity type</typeparam>
+    public class EFAsyncRepository<TEntity> : IAsyncRepository<TEntity>
+        where TEntity : class
+    {
+        private readonly Func<TEntity, object[], bool> _filterById;
+        private readonly DbSet<TEntity> _dbSet;
+        private readonly DbContext _dbContext;
+
+        /// <summary>
+        /// The Entity Framework database context
+        /// </summary>
+        protected DbContext DbContext
+        {
+            get { return _dbContext; }
+        }
+
+        /// <summary>
+        /// The <see cref="IDbSet{TEntity}"/> of this repository entity
+        /// </summary>
+        protected DbSet<TEntity> DbSet
+        {
+            get { return _dbSet; }
+        }
+
+        /// <summary>
+        /// Creates a new async repository
+        /// </summary>
+        /// <param name="dbContext">The database context</param>
+        /// <param name="filterById">The filter by the entity if expression</param>
+        /// <exception cref="ArgumentNullException"></exception>
+        public EFAsyncRepository(DbContext dbContext, Func<TEntity, object[], bool> filterById)
+        {
+            if (dbContext == null) throw new ArgumentNullException("dbContext");
+            if (filterById == null) throw new ArgumentNullException("filterById");
+
+            _filterById = filterById;
+            _dbContext = dbContext;
+            _dbSet = dbContext.Set<TEntity>();
+        }
+
+        #region Query
+
+        /// <summary>
+        /// Gets an <see cref="System.Linq.IQueryable{T}"/> for this repository entities
+        /// </summary>
+        /// <returns>The <see cref="System.Linq.IQueryable{T}"/> object</returns>
+        public IQueryable<TEntity> Query()
+        {
+            return DbSet;
+        }
+
+        /// <summary>
+        /// Gets an <see cref="IQueryable{TEntity}"/> for this repository entities
+        /// </summary>
+        /// <param name="ids">The entity unique identifiers</param>
+        /// <returns>The <see cref="IQueryable{TEntity}"/> object</returns>
+        public IQueryable<TEntity> QueryById(params object[] ids)
+        {
+            return Query().Where(e => _filterById(e, ids));
+        }
+
+        /// <summary>
+        /// Gets an <see cref="System.Linq.IQueryable{T}"/> for this repository entities
+        /// that will also fetch, on execution, all the entity navigation properties
+        /// </summary>
+        /// <param name="propertiesToFetch">The navigation properties to also fetch on query execution</param>
+        /// <returns>The <see cref="System.Linq.IQueryable{T}"/> object</returns>
+        /// <exception cref="ArgumentNullException"></exception>
+        public IQueryable<TEntity> QueryFetching(params Expression<Func<TEntity, object>>[] propertiesToFetch)
+        {
+            if (propertiesToFetch == null) throw new ArgumentNullException("propertiesToFetch");
+            return
+                propertiesToFetch
+                    .Aggregate<Expression<Func<TEntity, object>>, IQueryable<TEntity>>(
+                        DbSet, (current, expression) => current.Include(expression));
+        }
+
+        #endregion
+
+        #region GetById
+
+        /// <summary>
+        /// Gets an entity by its unique identifier from this repository asynchronously
+        /// </summary>
+        /// <param name="ids">The entity unique identifier</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> that will fetch the entity</returns>
+        public async Task<TEntity> GetByIdAsync(params object[] ids)
+        {
+            return await DbSet.FindAsync(ids);
+        }
+
+        /// <summary>
+        /// Gets an entity by its unique identifier from this repository asynchronously
+        /// </summary>
+        /// <param name="ids">The entity unique identifier</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> that will fetch the entity</returns>
+        public async Task<TEntity> GetByIdAsync(CancellationToken ct, params object[] ids)
+        {
+            return await DbSet.FindAsync(ct, ids);
+        }
+
+        #endregion
+
+        #region Add
+
+        /// <summary>
+        /// Adds the entity to the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to add</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> AddAsync(TEntity entity)
+        {
+            return await AddAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Adds the entity to the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to add</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> AddAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Add(entity));
+        }
+
+        /// <summary>
+        /// Adds a range of entities to the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entity to add</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> AddAsync(IEnumerable<TEntity> entities)
+        {
+            return await AddAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Adds a range of entities to the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entity to add</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> AddAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Add(entities));
+        }
+
+        #endregion
+
+        #region Update
+
+        /// <summary>
+        /// Updates the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to update</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> UpdateAsync(TEntity entity)
+        {
+            return await UpdateAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Updates the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to update</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> UpdateAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Update(entity));
+        }
+
+        /// <summary>
+        /// Updates a range of entities in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to update</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> UpdateAsync(IEnumerable<TEntity> entities)
+        {
+            return await UpdateAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Updates a range of entities in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to update</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> UpdateAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Update(entities));
+        }
+
+        #endregion
+
+        #region Delete
+
+        /// <summary>
+        /// Deletes the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to delete</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> DeleteAsync(TEntity entity)
+        {
+            return await DeleteAsync(entity, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Deletes the entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entity">The entity to delete</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entity</returns>
+        public async Task<TEntity> DeleteAsync(TEntity entity, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Delete(entity));
+        }
+
+        /// <summary>
+        /// Deletes a range of entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to delete</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> DeleteAsync(IEnumerable<TEntity> entities)
+        {
+            return await DeleteAsync(entities, CancellationToken.None);
+        }
+
+        /// <summary>
+        /// Deletes a range of entity in the repository asynchronously
+        /// </summary>
+        /// <param name="entities">The entities to delete</param>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the entities</returns>
+        public async Task<IEnumerable<TEntity>> DeleteAsync(IEnumerable<TEntity> entities, CancellationToken ct)
+        {
+            ct.ThrowIfCancellationRequested();
+            return await Task.FromResult(Delete(entities));
+        }
+
+        #endregion
+
+        #region Total
+
+        /// <summary>
+        /// Gets the total entities in the repository asynchronously
+        /// </summary>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the total</returns>
+        public async Task<long> TotalAsync()
+        {
+            return await DbSet.LongCountAsync();
+        }
+
+        /// <summary>
+        /// Gets the total entities in the repository asynchronously
+        /// </summary>
+        /// <param name="ct">The <see cref="System.Threading.CancellationToken"/> for the returned task</param>
+        /// <returns>A <see cref="System.Threading.Tasks.Task{TResult}"/> containing the total</returns>
+        public async Task<long> TotalAsync(CancellationToken ct)
+        {
+            return await DbSet.LongCountAsync(ct);
+        }
+
+        #endregion
+
+        #region Exists
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="ids">The entity unique identifiers</param>
+        /// <returns>True if entity exists</returns>
+        public bool Exists(params object[] ids)
+        {
+            return QueryById(ids).Any();
+        }
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="ids">The entity unique identifiers</param>
+        /// <returns>True if entity exists</returns>
+        public async Task<bool> ExistsAsync(params object[] ids)
+        {
+            return await QueryById(ids).AnyAsync();
+        }
+
+        /// <summary>
+        /// Checks if an entity with the given key exists
+        /// </summary>
+        /// <param name="ids">The entity unique identifiers</param>
+        /// <param name="ct">The <see cref="CancellationToken"/> for the returned task</param>
+        /// <returns>True if entity exists</returns>
+        public async Task<bool> ExistsAsync(CancellationToken ct, params object[] ids)
+        {
+            return await QueryById(ids).AnyAsync(ct);
+        }
+
+        #endregion
+
+        #region Private
+
+        private TEntity Add(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State == EntityState.Detached)
+                return DbSet.Add(entity);
+
+            dbEntityEntry.State = EntityState.Added;
+            return dbEntityEntry.Entity;
+        }
+
+        private IEnumerable<TEntity> Add(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return DbSet.AddRange(entities);
+        }
+
+        private TEntity Update(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State == EntityState.Detached)
+                DbSet.Attach(entity);
+            if (dbEntityEntry.State != EntityState.Added && dbEntityEntry.State != EntityState.Deleted)
+                dbEntityEntry.State = EntityState.Modified;
+
+            return dbEntityEntry.Entity;
+        }
+
+        private IEnumerable<TEntity> Update(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return entities.Select(Update).ToArray();
+        }
+
+        private TEntity Delete(TEntity entity)
+        {
+            var dbEntityEntry = DbContext.Entry(entity);
+            if (dbEntityEntry.State != EntityState.Deleted)
+            {
+                dbEntityEntry.State = EntityState.Deleted;
+                return dbEntityEntry.Entity;
+            }
+
+            DbSet.Attach(entity);
+            DbSet.Remove(entity);
+
+            return entity;
+        }
+
+        private IEnumerable<TEntity> Delete(IEnumerable<TEntity> entities)
+        {
+            if (entities == null) throw new ArgumentNullException("entities");
+            return entities.Select(Delete).ToArray();
+        }
+
+        #endregion
+    }
 }


Issue #147

Issue #147

--- SitecoreIntegrations/Applications/PowerShellResultViewerList.cs
+++ SitecoreIntegrations/Applications/PowerShellResultViewerList.cs
@@ -303,9 +303,9 @@
             Database scriptDb = Database.GetDatabase(message.Arguments["scriptDb"]);
             Item scriptItem = scriptDb.GetItem(message.Arguments["scriptID"]);

-            string sessionId = string.IsNullOrEmpty(ListViewer.SessionId)
+            string sessionId = string.IsNullOrEmpty(ListViewer.Data.SessionId)
                 ? scriptItem[ScriptItemFieldNames.PersistentSessionId]
-                : ListViewer.SessionId;
+                : ListViewer.Data.SessionId;
             ScriptSession scriptSession = ScriptSessionManager.GetSession(sessionId);

             String script = (scriptItem.Fields[ScriptItemFieldNames.Script] != null)
@@ -314,7 +314,7 @@
             List<object> results = ListViewer.SelectedItems.Select(p =>
             {
                 int id = Int32.Parse(p.Value);
-                return ListViewer.Data.Data[id].Original;
+                return ListViewer.Data.Data.Where(d => d.Id == id).Select(d => d.Original).First();
             }).ToList();
             scriptSession.SetVariable("resultSet", results);
             scriptSession.SetVariable("formatProperty", ListViewer.Data.Property);


cleanup

cleanup

--- SnapMD.ConnectedCare.ApiModels/Attributes/ModelNameAttribute.cs
+++ SnapMD.ConnectedCare.ApiModels/Attributes/ModelNameAttribute.cs
@@ -6,7 +6,7 @@
     /// Use this attribute to change the name of the <see cref="ModelDescription"/> generated for a type.
     /// </summary>
     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = false, Inherited = false)]
-    public sealed class ModelNameAttribute : Attribute
+    public class ModelNameAttribute : Attribute
     {
         public ModelNameAttribute(string name)
         {


Synchrophasor: Fixed a bug in initialization of FlatlineTest.

git-tfs-id: [https://tfs.codeplex.com/tfs/TFS07]$/openpdc/Synchrophasor/Current Version;C50427

--- Source/Libraries/Adapters/DataQualityMonitoring/FlatlineTest.cs
+++ Source/Libraries/Adapters/DataQualityMonitoring/FlatlineTest.cs
@@ -408,7 +408,7 @@
                 // Try to find the signal ID and add the measurement to the m_lastChange collection
                 if (DataSource.Tables.Contains("ActiveMeasurements"))
                 {
-                    DataRow[] measurementRows = DataSource.Tables["ActiveMeasurements"].Select(string.Format("Source = {0}", key.ToString()));
+                    DataRow[] measurementRows = DataSource.Tables["ActiveMeasurements"].Select(string.Format("ID = '{0}'", key.ToString()));

                     if (measurementRows.Length > 0)
                     {


Modify calculation of mouse wheel delta

Modify calculation of mouse wheel delta

--- Source/Monitorian.Core/Views/Controls/Sliders/EnhancedSlider.cs
+++ Source/Monitorian.Core/Views/Controls/Sliders/EnhancedSlider.cs
@@ -299,7 +299,7 @@

 		#region MouseWheel

-		private const double ReductionFactor = 0.05;
+		public static int WheelFactor { get; set; } = 5;

 		protected override void OnMouseWheel(MouseWheelEventArgs e)
 		{
@@ -311,7 +311,18 @@
 			if (e.Delta == 0)
 				return;

-			var newValue = this.Value + e.Delta * ReductionFactor;
+			// The default wheel rotation delta (for one notch) is set at 120.
+			// This value is seen as WHEEL_DELTA and System.Windows.Input.Mouse.MouseWheelDeltaForOneLine.
+			// Although a wheel rotation delta is expressed in multiples or divisions of WHEEL_DELTA,
+			// usually, it will be a multiple of WHEEL_DELTA (+120/-120).
+			// Some explanations are provided in:
+			// WM_MOUSEWHEEL Message
+			// https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mousewheel
+			// System.Windows.Forms.MouseEventArgs.Delta Property
+			// https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.mouseeventargs.delta
+			//
+			// Mouse.MouseWheelDeltaForOneLine should be casted to double in case the delta is smaller than 120.
+			var newValue = this.Value + (e.Delta / (double)Mouse.MouseWheelDeltaForOneLine * WheelFactor);
 			UpdateValue(newValue);
 			UpdateValueDeferred();
 		}


Modif beaver

Modif beaver

--- Unity/ludum-dare-32-PixelStuff/Assets/Scripts/Beavers/Beaver.cs
+++ Unity/ludum-dare-32-PixelStuff/Assets/Scripts/Beavers/Beaver.cs
@@ -91,16 +91,16 @@
 			//TO DO: Afficher Anim écrasé
 			//Debug.Log ("Ecrasé");

-			if (this.transform.localPosition.x <= -20f) {
+			if (this.transform.position.x <= -20f) {
 				Destroy (this.gameObject);
 			}
-			if(Time.time - m_timeSmashStateBegin >= 2){
+			if(Time.time - m_timeSmashStateBegin >= 5){
 				Destroy (this.gameObject);
 			}
 			break;
 		case BeaverState.Flying:
 			//TO DO: Lancer anim d'envole du beaver <3
-			if(Time.time - m_timeFlyStateBegin >= 2){
+			if(Time.time - m_timeFlyStateBegin >= 5){
 				Destroy (this.gameObject);
 			}
 			break;
@@ -119,7 +119,7 @@

 	void OnTriggerEnter2D(Collider2D collider){

-		if (collider.gameObject.tag == "Trunk" || collider.gameObject.tag == "SmashTree") {
+		if ((collider.gameObject.tag == "Trunk" || collider.gameObject.tag == "SmashTree") && m_currentState != BeaverState.HangOnTree) {
 			Debug.Log ("LANCER ANIMATION DE GERBE DE SANG");
 			changeState(BeaverState.Smashed);
 			m_life = 0;


Update TabUpdateMessage.cs

Update TabUpdateMessage.cs

--- UnityProject/Assets/Scripts/Messages/Server/TabUpdateMessage.cs
+++ UnityProject/Assets/Scripts/Messages/Server/TabUpdateMessage.cs
@@ -19,6 +19,9 @@
 	private static readonly ElementValue[] NoValues = new ElementValue[0];

 	private static Dictionary<int, ElementValue[]> ElementValuesCache = new Dictionary<int, ElementValue[]>();
+
+	private static HashSet<int> ServerUniqueIdCache = new HashSet<int>();
+
 	public int ID;
 	public int UniqueID;

@@ -87,9 +90,26 @@
 		ElementValue[] values = null)
 	{

-		if (tabAction == TabAction.Open)
-		{
-			values = NetworkTabManager.Instance.Get(provider, type).ElementValues;
+		switch (tabAction)
+		{
+			case TabAction.Open:
+				NetworkTabManager.Instance.Add(provider, type, recipient);
+				values = NetworkTabManager.Instance.Get(provider, type).ElementValues;
+				break;
+			case TabAction.Close:
+				NetworkTabManager.Instance.Remove(provider, type, recipient);
+				break;
+			case TabAction.Update:
+				//fixme: duplication of NetTab.ValidatePeepers
+				//Not sending updates and closing tab for players that don't pass the validation anymore
+				var validate = Validations.CanApply(recipient, provider, NetworkSide.Server);
+				if (!validate)
+				{
+					Send(recipient, provider, type, TabAction.Close);
+					return null;
+				}
+
+				break;
 		}

 		// SingleMessage: 0, start/middle: 1, end: 2
@@ -97,10 +117,12 @@

 		var uniqueID = Random.Range(0, 2000);

-		if (ElementValuesCache.ContainsKey(uniqueID))
+		if (ServerUniqueIdCache.Contains(uniqueID))
 		{
 			uniqueID = Random.Range(2001, 20000);
 		}
+
+		ServerUniqueIdCache.Add(uniqueID);

 		var elementValuesLists = new Dictionary<List<ElementValue>, int>();

@@ -160,8 +182,6 @@
 				elementValuesLists.Add(elementValues, 2);
 			}
 		}
-
-

 		if (elementValuesLists.Count == 0)
 		{
@@ -177,7 +197,8 @@
 				UniqueID = uniqueID
 			};

-			SendMessageOptions(recipient, provider, type, tabAction, msg);
+			msg.SendTo(recipient);
+			Logger.LogTraceFormat("{0}", Category.NetUI, msg);
 		}
 		else
 		{
@@ -195,39 +216,17 @@
 					UniqueID = uniqueID
 				};

-				SendMessageOptions(recipient, provider, type, tabAction, msg);
+				msg.SendTo(recipient);
+				Logger.LogTraceFormat("{0}", Category.NetUI, msg);
+
+				if (value.Value == 2)
+				{
+					ServerUniqueIdCache.Remove(uniqueID);
+				}
 			}
 		}

 		return null;
-	}
-
-	public static void SendMessageOptions(GameObject recipient, GameObject provider, NetTabType type, TabAction tabAction,
-		TabUpdateMessage msg)
-	{
-		switch (tabAction)
-		{
-			case TabAction.Open:
-				NetworkTabManager.Instance.Add(provider, type, recipient);
-				break;
-			case TabAction.Close:
-				NetworkTabManager.Instance.Remove(provider, type, recipient);
-				break;
-			case TabAction.Update:
-				//fixme: duplication of NetTab.ValidatePeepers
-				//Not sending updates and closing tab for players that don't pass the validation anymore
-				var validate = Validations.CanApply(recipient, provider, NetworkSide.Server);
-				if (!validate)
-				{
-					Send(recipient, provider, type, TabAction.Close);
-					return;
-				}
-
-				break;
-		}
-
-		msg.SendTo(recipient);
-		Logger.LogTraceFormat("{0}", Category.NetUI, msg);
 	}

 	//Merge arrays together


Delete AssemblyInfo.cs

Delete AssemblyInfo.cs


Replace use of obsoleted APIs

Replace use of obsoleted APIs

--- samples/Samples/Embedded/RDF/GettingStartedCore/Program.cs
+++ samples/Samples/Embedded/RDF/GettingStartedCore/Program.cs
@@ -49,7 +49,8 @@
             Console.WriteLine("Inserting RDF triples into store.");

             // execute a transaction to insert the data into the store
-            client.ExecuteTransaction(storeName, null, null, data.ToString());
+            var txnData = new UpdateTransactionData {InsertData = data.ToString()};
+            client.ExecuteTransaction(storeName, txnData);

             // SPARQL query for all the categories connected to BrightstarDB
             var query =
@@ -82,7 +83,8 @@

             Console.WriteLine("Executing SPARQL query for deletion against store.");
             Console.WriteLine(deletePatternsData);
-            client.ExecuteTransaction(storeName, null, deletePatternsData.ToString(), null);
+            txnData = new UpdateTransactionData {DeletePatterns = deletePatternsData.ToString()};
+            client.ExecuteTransaction(storeName, txnData);

             // SPARQL query for all the categories connected to BrightstarDB
             query =
@@ -106,7 +108,8 @@
             Console.WriteLine("Inserting RDF triples into store.");

             // execute a transaction to insert the data into the store
-            client.ExecuteTransaction(storeName, null, null, literals.ToString());
+            txnData = new UpdateTransactionData {InsertData = literals.ToString()};
+            client.ExecuteTransaction(storeName, txnData);

             const string queryAll = "SELECT ?o ?p ?l WHERE { ?o ?p ?l }";

@@ -125,7 +128,7 @@
                 Console.WriteLine("o= {0}\tp={1}\tl={2}", o, p, l);
             }

-            // Shutdown Brightstar processing threads
+            // Shutdown BrightstarDB processing threads
             BrightstarService.Shutdown();

             Console.WriteLine();


Unset turnEnded variable on opponent's turn

Should make it less likely to send bad messages to server or trigger
other weird behavior.

--- TimerChange.mod/TimerChange.cs
+++ TimerChange.mod/TimerChange.cs
@@ -98,9 +98,9 @@
                                 endTurnMethod.Invoke(target, new object[] { });
                             }
                         }
-                        else {
-                            turnEnded = false;
-                        }
+                    }
+                    else {
+                        turnEnded = false;
                     }
                 }
             }


Implementing the CheckForUpdatesTask

Implementing the CheckForUpdatesTask

--- UpdateLib/UpdateLib/Updater.cs
+++ UpdateLib/UpdateLib/Updater.cs
@@ -95,73 +95,99 @@
             if (!initialized)
                 throw new InvalidOperationException("The updater needs to be initialized first.");

-            if (String.IsNullOrEmpty(UpdateURL))
+            if (string.IsNullOrEmpty(UpdateURL))
                 throw new ArgumentException("You need to specifify a update url", "UpdateURL");
+
+            //WebClient wc = new WebClient();
+            //wc.DownloadFileCompleted += UpdateFile_DownloadCompleted;
+            //wc.DownloadFileAsync(new Uri(UpdateURL), m_localUpdateFile);
+
+            CheckForUpdatesTask task = new CheckForUpdatesTask(UpdateURL);
+            task.TaskCompleted += Task_TaskCompleted;
+            task.Start();

-            WebClient wc = new WebClient();
-            wc.DownloadFileCompleted += UpdateFile_DownloadCompleted;
-            wc.DownloadFileAsync(new Uri(UpdateURL), m_localUpdateFile);
-        }
-
-        private void UpdateFile_DownloadCompleted(object sender, AsyncCompletedEventArgs e)
-        {
-            WebClient download_client = (WebClient)sender;
-            download_client.Dispose();
-
-            // the update process got cancelled.
+        }
+
+        private void Task_TaskCompleted(object sender, AsyncCompletedEventArgs e)
+        {
+            if (e.Error != null)
+            {
+                MessageDialog msgError = new MessageDialog(
+                    "Error",
+                    "Unable to get the update information",
+                    "There has been a problem getting the needed update information \nPlease contact customer support!",
+                    SystemIcons.Error, MessageBoxButtons.OK);
+
+                msgError.ShowDialog();
+
+                return;
+            }
+
             if (e.Cancelled)
                 return;

-            // error reporting
-            if (e.Error != null)
-            {
-                Debug.WriteLine(String.Concat(e.Error.Message, "\n", e.Error.StackTrace));
-
-                if (ShowErrorMessage)
-                    new MessageDialog(
-                        "Error",
-                        "Unable to get the update information",
-                        "There has been a problem getting the needed update information  \nPlease contact customer support!",
-                        SystemIcons.Error, MessageBoxButtons.OK).ShowDialog();
-
-                return;
-            }
-
-            Action caller = new Action(CheckForUpdatesTask);
-            caller.BeginInvoke(new AsyncCallback(r => caller.EndInvoke(r)), null);
-        }
-
-        private void CheckForUpdatesTask()
-        {
-            UpdateFile updateFile = LoadUpdateFile();
-
-            HashCacheFile cache = GetCache();
-            CleanUpTask.AwaitTask();
-
-            CheckForUpdatedFilesTask checkForUpdatesTask = new CheckForUpdatedFilesTask(updateFile, cache, Converter);
-            checkForUpdatesTask.Start();
-            checkForUpdatesTask.AwaitTask();
-
-            Console.WriteLine("[INFO]: CheckForUpdatesTask: {0}", (checkForUpdatesTask.Result) ? "New version available!" : "Latest version!");
-
-            if (!checkForUpdatesTask.Result)
-                return;
-
-            DialogResult result = DialogResult.Yes;
-            if (ShowUpdateMessage)
-                result = new MessageDialog(
-                    "Update available",
-                    String.Format("Version {0} available", updateFile.VersionString),
-                    "Update now?\nPress yes to update or no to cancel.",
-                    SystemIcons.Question).ShowDialog();
-
-            if (result != DialogResult.Yes)
-                return;
-
-            // start actual updateform
-            UpdaterForm updateForm = new UpdaterForm(updateFile);
-            updateForm.ShowDialog();
-        }
+
+        }
+
+        //private void UpdateFile_DownloadCompleted(object sender, AsyncCompletedEventArgs e)
+        //{
+        //    WebClient download_client = (WebClient)sender;
+        //    download_client.Dispose();
+
+        //    // the update process got cancelled.
+        //    if (e.Cancelled)
+        //        return;
+
+        //    // error reporting
+        //    if (e.Error != null)
+        //    {
+        //        Debug.WriteLine(String.Concat(e.Error.Message, "\n", e.Error.StackTrace));
+
+        //        if (ShowErrorMessage)
+        //            new MessageDialog(
+        //                "Error",
+        //                "Unable to get the update information",
+        //                "There has been a problem getting the needed update information  \nPlease contact customer support!",
+        //                SystemIcons.Error, MessageBoxButtons.OK).ShowDialog();
+
+        //        return;
+        //    }
+
+        //    Action caller = new Action(CheckForUpdatesTask);
+        //    caller.BeginInvoke(new AsyncCallback(r => caller.EndInvoke(r)), null);
+        //}
+
+        //private void CheckForUpdatesTask()
+        //{
+        //    UpdateFile updateFile = LoadUpdateFile();
+
+        //    HashCacheFile cache = GetCache();
+        //    CleanUpTask.AwaitTask();
+
+        //    CheckForUpdatedFilesTask checkForUpdatesTask = new CheckForUpdatedFilesTask(updateFile, cache, Converter);
+        //    checkForUpdatesTask.Start();
+        //    checkForUpdatesTask.AwaitTask();
+
+        //    Console.WriteLine("[INFO]: CheckForUpdatesTask: {0}", (checkForUpdatesTask.Result) ? "New version available!" : "Latest version!");
+
+        //    if (!checkForUpdatesTask.Result)
+        //        return;
+
+        //    DialogResult result = DialogResult.Yes;
+        //    if (ShowUpdateMessage)
+        //        result = new MessageDialog(
+        //            "Update available",
+        //            String.Format("Version {0} available", updateFile.VersionString),
+        //            "Update now?\nPress yes to update or no to cancel.",
+        //            SystemIcons.Question).ShowDialog();
+
+        //    if (result != DialogResult.Yes)
+        //        return;
+
+        //    // start actual updateform
+        //    UpdaterForm updateForm = new UpdaterForm(updateFile);
+        //    updateForm.ShowDialog();
+        //}

         public HashCacheFile GetCache()
         {
@@ -169,13 +195,6 @@
             return UpdateCacheTask.Result;
         }

-        private UpdateFile LoadUpdateFile()
-        {
-            return UpdateFile.Load(m_localUpdateFile);
-        }
-
-
-
         private string GetRemoteBasePath()
         {
             string[] tokens = UpdateURL.Split('/');


uses QuickGraph now

uses QuickGraph now

--- VS/CSHARP/asm-sim-lib/CFlow.cs
+++ VS/CSHARP/asm-sim-lib/CFlow.cs
@@ -35,23 +35,25 @@
         public static readonly char LINENUMBER_SEPARATOR = '!';

         private string _programStr = "";
-        private IList<(string label, Mnemonic mnemonic, string[] args)> _sourceCode;
-        private readonly IDictionary<int, IList<(int lineNumber, bool isBranch)>> _incomingLines;
-
-        //private readonly BidirectionalGraph<int, IEdge<int>> _data; //TODO use QuickGraph
+        private readonly IList<(string label, Mnemonic mnemonic, string[] args)> _sourceCode;
+        private readonly BidirectionalGraph<int, TaggedEdge<int, bool>> _graph;

         /// Constructor that creates an empty CFlow
         public CFlow() : this("") {}

         public CFlow(string programStr)
         {
-            this._incomingLines = new Dictionary<int, IList<(int lineNumber, bool isBranch)>>();
+            //Console.WriteLine("INFO: CFlow: constructor");
+            this._sourceCode = new List<(string label, Mnemonic mnemonic, string[] args)>(programStr.Length);
+            this._graph = new BidirectionalGraph<int, TaggedEdge<int, bool>>(true); // true because of conditional jump to the next line
             this.Update(programStr);
         }

+        #region Setters
         /// Update this CFlow with the provided programStr: return true if this CFlow has changed.
         public bool Update(string programStr)
         {
+            //Console.WriteLine("INFO: CFlow:Update");
             //TODO make intelligent code: return true if something has changed.
             //if (this._programStr.Equals(programStr,StringComparison.OrdinalIgnoreCase))
             //{
@@ -59,14 +61,16 @@
             //    return false;
             //}
             this._programStr = programStr;
-            this._incomingLines.Clear();
-            this._sourceCode = this.GetLines(programStr);
+            this.Update_Lines(programStr);
             return true;
         }
+        #endregion
+
+        #region Getters

         public int NLines { get { return this._sourceCode.Count; } }

-        public int LastLineNumber {  get { return this._sourceCode.Count; } }
+        public int LastLineNumber { get { return this._sourceCode.Count; } }

         public bool HasLine(int lineNumber)
         {
@@ -116,7 +120,7 @@

         public bool Has_Prev_LineNumber(int lineNumber)
         {
-            return this._incomingLines.ContainsKey(lineNumber);
+            return this._graph.IsInEdgesEmpty(lineNumber);
         }

         ///
@@ -124,41 +128,29 @@
         ///
         public IEnumerable<(int LineNumber, bool IsBranch)> GetPrevLineNumber(int lineNumber)
         {
-            if (this._incomingLines.TryGetValue(lineNumber, out IList<(int, bool)> incoming))
-            {
-                return incoming;
-            }
-            return Enumerable.Empty<(int LineNumber, bool IsBranch)>();
+            foreach (var v in this._graph.InEdges(lineNumber))
+            {
+                yield return (v.Source, v.Tag);
+            }
         }

         public (int Regular, int Branch) GetNextLineNumber(int lineNumber)
         {
-            int lineNumberRegular = -1;
-            int lineNumberBranch = -1;
-
-            //TODO make faster!!
-            foreach (var x in this._incomingLines)
-            {
-                foreach (var y in x.Value)
-                {
-                    if (y.lineNumber == lineNumber)
-                    {
-                        if (y.isBranch)
-                        {
-                            lineNumberBranch = x.Key;
-                        }
-                        else
-                        {
-                            lineNumberRegular = x.Key;
-                        }
-                        if ((lineNumberBranch != -1) && (lineNumberRegular != -1))
-                        {
-                            return (Regular: lineNumberRegular, Branch: lineNumberBranch);
-                        }
-                    }
-                }
-            }
-            return (Regular: lineNumberRegular, Branch: lineNumberBranch);
+            int Regular = -1;
+            int Branch = -1;
+
+            foreach (var v in this._graph.OutEdges(lineNumber))
+            {
+                if (v.Tag)
+                {
+                    Branch = v.Target;
+                }
+                else
+                {
+                    Regular = v.Target;
+                }
+            }
+            return (Regular: Regular, Branch: Branch);
         }

         /// A LoopBranchPoint is a BranchPoint that choices between leaving the loop or staying in the loop.
@@ -197,7 +189,7 @@
                     if (HasCodePath(lineNumber, v.LineNumber))
                     {
                         numberOfLoops++;
-                        loopLineNumber = v.LineNumber;
+                        loopLineNumber = v.LineNumber;
                     }
                 }
                 if (numberOfLoops > 0)
@@ -239,7 +231,7 @@
             if (this.HasLine(lineNumber))
             {
                 var lineContent = this.GetLine(lineNumber);
-                StaticJump(lineContent.Mnemonic, lineContent.Args, lineNumber, out int jumpTo1, out int jumpTo2);
+                Static_Jump(lineContent.Mnemonic, lineContent.Args, lineNumber, out int jumpTo1, out int jumpTo2);
                 return ((jumpTo1 >= 0) && (jumpTo2 >= 0));
             }
             else
@@ -254,6 +246,8 @@
             var enumerator = this.GetPrevLineNumber(lineNumber).GetEnumerator();
             return (enumerator.MoveNext() && enumerator.MoveNext());
         }
+
+        #endregion

         #region ToString Methods

@@ -305,8 +299,10 @@

         #region Private Methods

-        private IList<(string label, Mnemonic mnemonic, string[] args)> GetLines(string programStr)
-        {
+        private void Update_Lines(string programStr)
+        {
+            //Console.WriteLine("INFO: CFlow:Update_Lines");
+
             #region parse to find all labels
             IDictionary<string, int> labels = this.GetLabels(programStr);
             // replace all labels by annotated label
@@ -323,39 +319,41 @@
             #endregion
             #region Populate IncomingLines
             string[] lines = programStr.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
-            IList<(string, Mnemonic, string[])> data = new List<(string, Mnemonic, string[])>(lines.Length);
+
+            this._sourceCode.Clear();
+
             for (int lineNumber = 0; lineNumber < lines.Length; ++lineNumber)
             {
                 var line = AsmSourceTools.ParseLine(lines[lineNumber]);
-                data.Add((line.Label, line.Mnemonic, line.Args));
-
-                this.StaticJump(line.Mnemonic, line.Args, lineNumber, out int jumpTo1, out int jumpTo2);
+                this._sourceCode.Add((line.Label, line.Mnemonic, line.Args));
+
+                this.Static_Jump(line.Mnemonic, line.Args, lineNumber, out int jumpTo1, out int jumpTo2);
                 if (jumpTo1 != -1)
                 {
-                    this.AddToIncomingLines(lineNumber, jumpTo1, false);
+                    this.Add_Edge(lineNumber, jumpTo1, false);
                 }
                 if (jumpTo2 != -1)
                 {
-                    this.AddToIncomingLines(lineNumber, jumpTo2, true);
+                    this.Add_Edge(lineNumber, jumpTo2, true);
                 }
             }
             #endregion
-            return data;
-        }
-
-        private void AddToIncomingLines(int jumpFrom, int jumpTo, bool isBranch)
-        {
-            if (this._incomingLines.ContainsKey(jumpTo))
-            {
-                this._incomingLines[jumpTo].Add((jumpFrom, isBranch));
-            }
-            else
-            {
-                this._incomingLines.Add(jumpTo, new List<(int, bool)> { (jumpFrom, isBranch) });
-            }
-        }
-
-        private void StaticJump(Mnemonic mnemonic, string[] args, int lineNumber, out int jumpTo1, out int jumpTo2)
+        }
+
+        private void Add_Edge(int jumpFrom, int jumpTo, bool isBranch)
+        {
+            //Console.WriteLine("INFO: from " + jumpFrom + " to " + jumpTo + " (branch " + isBranch + ")");
+            if (!this._graph.ContainsVertex(jumpFrom)) this._graph.AddVertex(jumpFrom);
+            if (!this._graph.ContainsVertex(jumpTo)) this._graph.AddVertex(jumpTo);
+
+            //if (this._graph.ContainsEdge(jumpFrom, jumpTo)) {
+            //    Console.WriteLine("INFO: Edge already exists: from " + jumpFrom + " to " + jumpTo + " (branch " + isBranch + ")");
+            //}
+
+            this._graph.AddEdge(new TaggedEdge<int, bool>(jumpFrom, jumpTo, isBranch));
+        }
+
+        private void Static_Jump(Mnemonic mnemonic, string[] args, int lineNumber, out int jumpTo1, out int jumpTo2)
         {
             jumpTo1 = -1;
             jumpTo2 = -1;
@@ -420,7 +418,7 @@
                 case Mnemonic.RET:
                 case Mnemonic.IRET:
                 case Mnemonic.INT:
-                case Mnemonic.INTO:
+                case Mnemonic.INTO: return;
                    //throw new NotImplementedException();
                 default:
                     jumpTo1 = lineNumber + 1;


changed defaulot model status text

changed defaulot model status text

--- Views/Home/APITestDrive.cshtml
+++ Views/Home/APITestDrive.cshtml
@@ -133,7 +133,7 @@

-
Latest model:

+
Model is not ready, the trainer takes 2 - 10 minutes to start on a fresh deployment.

                 <button onclick="resetModel()" class="btn btn-primary btn-group-sm" style="margin-bottom:15px">Reset Model</button>


Added comments on XML serialization.

Added comments on XML serialization.

--- WoDCharacterData/BoundedInt.cs
+++ WoDCharacterData/BoundedInt.cs
@@ -12,6 +12,8 @@
     /// or "greater than" another object of the same type.
     ///
     /// The bounded generic object can be converted between itself and the generic type, and compared against itself and the generic type.
+    ///
+    /// Bounded objects can be serialized to XML - the value will become the text value of the node, and the Min and Max will be attributes.
     /// </summary>
     /// <typeparam name="T"></typeparam>
     public class Bounded<T> :
@@ -38,6 +40,9 @@
         #endregion Constructors

         #region Properties
+        /// <summary>
+        /// The actual value of the bounded object. This is the value used in comparisons. . XMLSerialized as #text
+        /// </summary>
         [XmlText()]
         public T Value {
             get {
@@ -52,6 +57,9 @@
             }
         }

+        /// <summary>
+        /// The minimum value of the bounded object. XMLSerialized as @Min
+        /// </summary>
         [XmlAttribute("Min")]
         public T Min {
             get {
@@ -64,6 +72,9 @@
             }
         }

+        /// <summary>
+        /// The maximum value of the bounded object. XMLSerialized as @Max
+        /// </summary>
         [XmlAttribute("Max")]
         public T Max
         {


Return empty result when there are no credentials on the system.

--- poshring/CredentialsManager.cs
+++ poshring/CredentialsManager.cs
@@ -14,7 +14,17 @@
             IntPtr ptr;
             if (!UnsafeAdvapi32.CredEnumerateW(null, 0x1, out count, out ptr))
             {
-                throw new Win32Exception(Marshal.GetLastWin32Error());
+                var error = (CredentialErrors) Marshal.GetLastWin32Error();
+                switch (error)
+                {
+                    case CredentialErrors.NotFound:
+                        return Enumerable.Empty<Credential>();
+                    case CredentialErrors.NoSuchLogonSession:
+                    case CredentialErrors.InvalidFlags:
+                        throw new Win32Exception((int)error);
+                    default:
+                        throw new InvalidOperationException("Unexpected error while fetching credentials.");
+                }
             }

             var credentials = Enumerable.Range(0, count)


bump version

bump version

--- XSTerm/Properties/AddinInfo.cs
+++ XSTerm/Properties/AddinInfo.cs
@@ -5,7 +5,7 @@
 [assembly: Addin(
 	"XSTerm",
 	Namespace = "XSTerm",
-	Version = "1.0"
+	Version = "1.0.1"
 )]

 [assembly: AddinName("XSTerm")]


Reduce a little code duplication

Reduce a little code duplication

--- XamarinStripe/StripePayment.cs
+++ XamarinStripe/StripePayment.cs
@@ -63,6 +63,12 @@
             }
         }

+        protected virtual T DoRequest<T> (string endpoint, string method = "GET", string body = null)
+        {
+            var json = DoRequest (endpoint, method, body);
+            return JsonConvert.DeserializeObject<T> (json);
+        }
+
         protected virtual string DoRequest (string endpoint)
         {
             return DoRequest (endpoint, "GET", null);
@@ -151,8 +157,7 @@
             }
             str.Length--;
             string ep = String.Format ("{0}/charges", api_endpoint);
-            string json = DoRequest (ep, "POST", str.ToString ());
-            return JsonConvert.DeserializeObject<StripeCharge> (json);
+            return DoRequest<StripeCharge> (ep, "POST", str.ToString ());
         }

         public StripeCharge GetCharge (string charge_id)
@@ -161,8 +166,7 @@
                 throw new ArgumentNullException ("charge_id");

             string ep = String.Format ("{0}/charges/{1}", api_endpoint, HttpUtility.UrlEncode (charge_id));
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCharge> (json);
+            return DoRequest<StripeCharge> (ep);
         }

         public StripeCollection<StripeCharge> GetCharges (int offset = 0, int count = 10, string customer_id = null)
@@ -180,8 +184,7 @@

             str.Length--;
             string ep = String.Format ("{0}/charges?{1}", api_endpoint, str);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCollection<StripeCharge>> (json);
+            return DoRequest<StripeCollection<StripeCharge>> (ep);
         }

         public StripeDispute UpdateDispute (string charge_id, string evidence)
@@ -193,8 +196,7 @@
                 throw new ArgumentNullException ("evidence");

             string ep = String.Format ("{0}/charges/{1}/disput", api_endpoint, HttpUtility.UrlEncode (charge_id), HttpUtility.UrlEncode (evidence));
-            string json = DoRequest (ep, "POST", String.Format ("evidence={0}", HttpUtility.UrlEncode (evidence)));
-            return JsonConvert.DeserializeObject<StripeDispute> (json);
+            return DoRequest<StripeDispute> (ep, "POST", String.Format ("evidence={0}", HttpUtility.UrlEncode (evidence)));
         }

         #endregion
@@ -205,8 +207,7 @@
                 throw new ArgumentNullException ("charge_id");

             string ep = String.Format ("{0}/charges/{1}/refund", api_endpoint, HttpUtility.UrlEncode (charge_id));
-            string json = DoRequest (ep, "POST", null);
-            return JsonConvert.DeserializeObject<StripeCharge> (json);
+            return DoRequest<StripeCharge> (ep, "POST", null);
         }

         public StripeCharge Refund (string charge_id, int amount)
@@ -217,8 +218,7 @@
                 throw new ArgumentException ("Amount must be greater than zero.", "amount");

             string ep = String.Format ("{0}/charges/{1}/refund?amount={2}", api_endpoint, HttpUtility.UrlEncode (charge_id), amount);
-            string json = DoRequest (ep, "POST", null);
-            return JsonConvert.DeserializeObject<StripeCharge> (json);
+            return DoRequest<StripeCharge> (ep, "POST", null);
         }
         #endregion
         #region Customer
@@ -230,8 +230,7 @@
             if (id != null)
                 format = "{0}/customers/{1}"; // Update
             string ep = String.Format (format, api_endpoint, HttpUtility.UrlEncode (id));
-            string json = DoRequest (ep, "POST", str.ToString ());
-            return JsonConvert.DeserializeObject<StripeCustomer> (json);
+            return DoRequest<StripeCustomer> (ep, "POST", str.ToString ());
         }

         public StripeCustomer CreateCustomer (StripeCustomerInfo customer)
@@ -258,8 +257,7 @@
                 throw new ArgumentNullException ("customer_id");

             string ep = String.Format ("{0}/customers/{1}", api_endpoint, HttpUtility.UrlEncode (customer_id));
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCustomer> (json);
+            return DoRequest<StripeCustomer> (ep);
         }

         public StripeCollection<StripeCustomer> GetCustomers (int offset = 0, int count = 10)
@@ -271,8 +269,7 @@

             string str = String.Format ("offset={0}&count={1}", offset, count);
             string ep = String.Format ("{0}/customers?{1}", api_endpoint, str);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCollection<StripeCustomer>> (json);
+            return DoRequest<StripeCollection<StripeCustomer>> (ep);
         }

         public StripeCustomer DeleteCustomer (string customer_id)
@@ -281,16 +278,14 @@
                 throw new ArgumentNullException ("customer_id");

             string ep = String.Format ("{0}/customers/{1}", api_endpoint, HttpUtility.UrlEncode (customer_id));
-            string json = DoRequest (ep, "DELETE", null);
-            return JsonConvert.DeserializeObject<StripeCustomer> (json);
+            return DoRequest<StripeCustomer> (ep, "DELETE", null);
         }
         #endregion
         #region Events
         public StripeEvent GetEvent (string eventId)
         {
             string ep = string.Format ("{0}/events/{1}", api_endpoint, HttpUtility.UrlEncode (eventId));
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeEvent> (json);
+            return DoRequest<StripeEvent> (ep);
         }

         public StripeCollection<StripeEvent> GetEvents (int offset = 0, int count = 10, string type = null)
@@ -307,9 +302,7 @@
                 args += String.Format ("&type={0}", HttpUtility.UrlEncode (type));

             string ep = String.Format ("{0}/events?{1}", api_endpoint, args);
-
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCollection<StripeEvent>> (json);
+            return DoRequest<StripeCollection<StripeEvent>> (ep);
         }

         #endregion
@@ -322,8 +315,7 @@
             StringBuilder str = UrlEncode (card);

             string ep = string.Format ("{0}/tokens", api_endpoint);
-            string json = DoRequest (ep, "POST", str.ToString ());
-            return JsonConvert.DeserializeObject<StripeCreditCardToken> (json);
+            return DoRequest<StripeCreditCardToken> (ep, "POST", str.ToString ());
         }

         public StripeCreditCardToken GetToken (string tokenId)
@@ -332,8 +324,7 @@
                 throw new ArgumentNullException (tokenId);

             string ep = string.Format ("{0}/tokens/{1}", api_endpoint, HttpUtility.UrlEncode (tokenId));
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCreditCardToken> (json);
+            return DoRequest<StripeCreditCardToken> (ep);
         }
         #endregion
         #region Plans
@@ -344,8 +335,7 @@
             StringBuilder str = UrlEncode (plan);

             string ep = string.Format ("{0}/plans", api_endpoint);
-            string json = DoRequest (ep, "POST", str.ToString ());
-            return JsonConvert.DeserializeObject<StripePlan> (json);
+            return DoRequest<StripePlan> (ep, "POST", str.ToString ());
         }

         public StripePlan GetPlan (string planId)
@@ -354,8 +344,7 @@
                 throw new ArgumentNullException ("id");

             string ep = string.Format ("{0}/plans/{1}", api_endpoint, HttpUtility.UrlEncode (planId));
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripePlan> (json);
+            return DoRequest<StripePlan> (ep);
         }

         public StripePlan DeletePlan (string planId)
@@ -364,16 +353,14 @@
                 throw new ArgumentNullException ("id");

             string ep = string.Format ("{0}/plans/{1}", api_endpoint, HttpUtility.UrlEncode (planId));
-            string json = DoRequest (ep, "DELETE", null);
-            return JsonConvert.DeserializeObject<StripePlan> (json);
+            return DoRequest<StripePlan> (ep, "DELETE", null);
         }

         public StripeCollection<StripePlan> GetPlans (int offset = 0, int count = 10)
         {
             string str = string.Format ("count={0}&offset={1}", count, offset);
             string ep = string.Format ("{0}/plans?{1}", api_endpoint, str);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCollection<StripePlan>> (json);
+            return DoRequest<StripeCollection<StripePlan>> (ep);
         }
         #endregion
         #region Subscriptions
@@ -381,8 +368,7 @@
         {
             StringBuilder str = UrlEncode (subscription);
             string ep = string.Format (subscription_path, api_endpoint, HttpUtility.UrlEncode (customerId));
-            string json = DoRequest (ep, "POST", str.ToString ());
-            return JsonConvert.DeserializeObject<StripeSubscription> (json);
+            return DoRequest<StripeSubscription> (ep, "POST", str.ToString ());
         }

         public StripeSubscription GetSubscription (string customerId)
@@ -390,15 +376,13 @@
             if (string.IsNullOrEmpty (customerId))
                 throw new ArgumentNullException ("customerId");
             string ep = string.Format (subscription_path, api_endpoint, HttpUtility.UrlEncode (customerId));
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeSubscription> (json);
+            return DoRequest<StripeSubscription>(ep);
         }

         public StripeSubscription Unsubscribe (string customerId, bool atPeriodEnd)
         {
             string ep = string.Format (subscription_path + "?at_period_end={2}", api_endpoint, HttpUtility.UrlEncode (customerId), atPeriodEnd.ToString (CultureInfo.InvariantCulture).ToLowerInvariant ());
-            string json = DoRequest (ep, "DELETE", null);
-            return JsonConvert.DeserializeObject<StripeSubscription> (json);
+            return DoRequest<StripeSubscription> (ep, "DELETE", null);
         }
         #endregion
         #region Invoice items
@@ -408,8 +392,7 @@
                 throw new ArgumentNullException ("item.CustomerID");
             StringBuilder str = UrlEncode (item);
             string ep = string.Format ("{0}/invoiceitems", api_endpoint);
-            string json = DoRequest (ep, "POST", str.ToString ());
-            return JsonConvert.DeserializeObject<StripeInvoiceItem> (json);
+            return DoRequest<StripeInvoiceItem> (ep, "POST", str.ToString ());
         }

         public StripeInvoiceItem GetInvoiceItem (string invoiceItemId)
@@ -417,23 +400,20 @@
             if (string.IsNullOrEmpty (invoiceItemId))
                 throw new ArgumentNullException ("invoiceItemId");
             string ep = string.Format ("{0}/invoiceitems/{1}", api_endpoint, invoiceItemId);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeInvoiceItem> (json);
+            return DoRequest<StripeInvoiceItem> (ep);
         }

         public StripeInvoiceItem UpdateInvoiceItem (string invoiceItemId, StripeInvoiceItemInfo item)
         {
             StringBuilder str = UrlEncode (item);
             string ep = string.Format ("{0}/invoiceitems/{1}", api_endpoint, invoiceItemId);
-            string json = DoRequest (ep, "POST", str.ToString ());
-            return JsonConvert.DeserializeObject<StripeInvoiceItem> (json);
+            return DoRequest<StripeInvoiceItem> (ep, "POST", str.ToString ());
         }

         public StripeInvoiceItem DeleteInvoiceItem (string invoiceItemId)
         {
             string ep = string.Format ("{0}/invoiceitems/{1}", api_endpoint, invoiceItemId);
-            string json = DoRequest (ep, "DELETE", null);
-            return JsonConvert.DeserializeObject<StripeInvoiceItem> (json);
+            return DoRequest<StripeInvoiceItem> (ep, "DELETE", null);
         }

         public StripeCollection<StripeInvoiceItem> GetInvoiceItems (int offset = 0, int count = 10, string customerId = null)
@@ -451,8 +431,7 @@

             str.Length--;
             string ep = String.Format ("{0}/invoiceitems?{1}", api_endpoint, str);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCollection<StripeInvoiceItem>> (json);
+            return DoRequest<StripeCollection<StripeInvoiceItem>> (ep);
         }

         #endregion
@@ -462,8 +441,7 @@
             if (string.IsNullOrEmpty (invoiceId))
                 throw new ArgumentNullException ("invoiceId");
             string ep = string.Format ("{0}/invoices/{1}", api_endpoint, invoiceId);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeInvoice> (json);
+            return DoRequest<StripeInvoice> (ep);
         }

         public StripeCollection<StripeInvoice> GetInvoices (int offset = 0, int count = 10, string customerId = null)
@@ -481,8 +459,7 @@

             str.Length--;
             string ep = String.Format ("{0}/invoices?{1}", api_endpoint, str);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCollection<StripeInvoice>> (json);
+            return DoRequest<StripeCollection<StripeInvoice>>(ep);
         }

         public StripeInvoice GetUpcomingInvoice (string customerId)
@@ -490,8 +467,7 @@
             if (string.IsNullOrEmpty (customerId))
                 throw new ArgumentOutOfRangeException ("customerId");
             string ep = String.Format ("{0}/invoices/upcoming?customer={1}", api_endpoint, customerId);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeInvoice> (json);
+            return DoRequest<StripeInvoice> (ep);
         }

         public StripeCollection<StripeLineItem> GetInvoiceLines (string invoiceId)
@@ -499,8 +475,7 @@
             if (string.IsNullOrEmpty (invoiceId))
                 throw new ArgumentNullException ("invoiceId");
             string ep = string.Format ("{0}/invoices/{1}/lines", api_endpoint, invoiceId);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCollection<StripeLineItem>> (json);
+            return DoRequest<StripeCollection<StripeLineItem>> (ep);
         }
         #endregion
         #region Coupons
@@ -514,8 +489,7 @@
                 throw new ArgumentException ("MonthsForDuration must be greater than 1 when Duration = Repeating");
             StringBuilder str = UrlEncode (coupon);
             string ep = string.Format ("{0}/coupons", api_endpoint);
-            string json = DoRequest (ep, "POST", str.ToString ());
-            return JsonConvert.DeserializeObject<StripeCoupon> (json);
+            return DoRequest<StripeCoupon> (ep, "POST", str.ToString ());
         }

         public StripeCoupon GetCoupon (string couponId)
@@ -523,8 +497,7 @@
             if (string.IsNullOrEmpty (couponId))
                 throw new ArgumentNullException ("couponId");
             string ep = string.Format ("{0}/coupons/{1}", api_endpoint, couponId);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCoupon> (json);
+            return DoRequest<StripeCoupon> (ep);
         }

         public StripeCoupon DeleteCoupon (string couponId)
@@ -532,8 +505,7 @@
             if (string.IsNullOrEmpty (couponId))
                 throw new ArgumentNullException ("couponId");
             string ep = string.Format ("{0}/coupons/{1}", api_endpoint, couponId);
-            string json = DoRequest (ep, "DELETE", null);
-            return JsonConvert.DeserializeObject<StripeCoupon> (json);
+            return DoRequest<StripeCoupon> (ep, "DELETE", null);
         }

         public StripeCollection<StripeCoupon> GetCoupons (int offset = 0, int count = 10)
@@ -543,8 +515,7 @@
             if (count > 100)
                 throw new ArgumentOutOfRangeException ("count");
             string ep = string.Format ("{0}/coupons?offset={0}&count={1}", api_endpoint, offset, count);
-            string json = DoRequest (ep);
-            return JsonConvert.DeserializeObject<StripeCollection<StripeCoupon>> (json);
+            return DoRequest<StripeCollection<StripeCoupon>> (ep);
         }
         #endregion
         public int TimeoutSeconds { get; set; }


ViewBackend Mac keyDown and keyUp (mostly) working now

--- Xwt.Mac/Xwt.Mac/ViewBackend.cs
+++ Xwt.Mac/Xwt.Mac/ViewBackend.cs
@@ -491,6 +491,10 @@
 				WidgetEvent ev = (WidgetEvent) eventId;
 				currentEvents |= ev;
 				switch (ev) {
+				case WidgetEvent.KeyPressed:
+				case WidgetEvent.KeyReleased:
+					SetupKeyEvents (Widget.GetType ());
+					break;
 				case WidgetEvent.GotFocus:
 				case WidgetEvent.LostFocus:
 					SetupFocusEvents (Widget.GetType ());
@@ -498,7 +502,7 @@
 				}
 			}
 		}
-
+
 		public virtual void DisableEvent (object eventId)
 		{
 			if (eventId is WidgetEvent) {
@@ -506,7 +510,7 @@
 				currentEvents &= ~ev;
 			}
 		}
-
+
 		static Selector draggingEnteredSel = new Selector ("draggingEntered:");
 		static Selector draggingUpdatedSel = new Selector ("draggingUpdated:");
 		static Selector draggingExitedSel = new Selector ("draggingExited:");
@@ -515,9 +519,12 @@
 		static Selector concludeDragOperationSel = new Selector ("concludeDragOperation:");
 		static Selector becomeFirstResponderSel = new Selector ("becomeFirstResponder");
 		static Selector resignFirstResponderSel = new Selector ("resignFirstResponder");
+		static Selector keyDownSel = new Selector ("keyDown:");
+		static Selector keyUpSel = new Selector ("keyUp:");

 		static HashSet<Type> typesConfiguredForDragDrop = new HashSet<Type> ();
 		static HashSet<Type> typesConfiguredForFocusEvents = new HashSet<Type> ();
+		static HashSet<Type> typesConfiguredForKeyEvents = new HashSet<Type> ();

 		static void SetupForDragDrop (Type type)
 		{
@@ -544,7 +551,42 @@
 				}
 			}
 		}
-
+
+		static void SetupKeyEvents (Type type)
+		{
+			lock (typesConfiguredForKeyEvents) {
+				if (typesConfiguredForKeyEvents.Add (type)) {
+					Class c = new Class (type);
+					c.AddMethod (keyDownSel.Handle, new Action<IntPtr,IntPtr,IntPtr> (OnKeyDown), "v@:@");
+					c.AddMethod (keyUpSel.Handle, new Action<IntPtr,IntPtr,IntPtr> (OnKeyUp), "v@:@");
+				}
+			}
+		}
+
+		static void OnKeyDown (IntPtr sender, IntPtr sel, IntPtr evt)
+		{
+			IViewObject ob = Runtime.GetNSObject (sender) as IViewObject;
+			if (ob == null)
+				return;
+			NSEvent evnt = new NSEvent(evt);
+			// TODO this is bogus
+			KeyEventArgs kea = new KeyEventArgs(Key.Return, ModifierKeys.None, false, 0);
+			// TODO translate evnt to the thing
+			ob.Backend.EventSink.OnKeyPressed(kea);
+		}
+
+		static void OnKeyUp (IntPtr sender, IntPtr sel, IntPtr evt)
+		{
+			IViewObject ob = Runtime.GetNSObject (sender) as IViewObject;
+			if (ob == null)
+				return;
+			NSEvent evnt = new NSEvent(evt);
+			// TODO this is bogus
+			KeyEventArgs kea = new KeyEventArgs(Key.Return, ModifierKeys.None, false, 0);
+			// TODO translate evnt to the thing
+			ob.Backend.EventSink.OnKeyReleased(kea);
+		}
+
 		public void DragStart (DragStartData sdata)
 		{
 			var lo = Widget.ConvertPointToBase (new PointF (Widget.Bounds.X, Widget.Bounds.Y));