Skip to content

Commit

Permalink
Merge pull request #604 from johelvisguzman/GH-603
Browse files Browse the repository at this point in the history
(GH-603) Added a new repository interception context object
  • Loading branch information
johelvisguzman authored Mar 26, 2020
2 parents 3727ed4 + 005913c commit 9cd5939
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,48 @@ public interface IRepositoryInterceptor
/// An activity method which is executed when adding an entity to the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
void AddExecuting<TEntity>(TEntity entity);
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
void AddExecuting<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext) where TEntity : class;

/// <summary>
/// An activity method which is executed when deleting an entity from the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
void DeleteExecuting<TEntity>(TEntity entity);
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
void DeleteExecuting<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext) where TEntity : class;

/// <summary>
/// An activity method which is executed when updating an entity in the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
void UpdateExecuting<TEntity>(TEntity entity);
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
void UpdateExecuting<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext) where TEntity : class;

/// <summary>
/// Asynchronously an activity method which is executed when adding an entity to the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
Task AddExecutingAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken());
Task AddExecutingAsync<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext, CancellationToken cancellationToken = new CancellationToken()) where TEntity : class;

/// <summary>
/// Asynchronously an activity method which is executed when deleting an entity from the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
Task DeleteExecutingAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken());
Task DeleteExecutingAsync<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext, CancellationToken cancellationToken = new CancellationToken()) where TEntity : class;

/// <summary>
/// Asynchronously an activity method which is executed when updating an entity in the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
Task UpdateExecutingAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken());
Task UpdateExecutingAsync<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext, CancellationToken cancellationToken = new CancellationToken()) where TEntity : class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace DotNetToolkit.Repository.Configuration.Interceptors
{
using JetBrains.Annotations;
using Utility;

/// <summary>
/// Represents contextual information associated with calls into <see cref="IRepositoryInterceptor" />.
/// </summary>
/// <typeparam name="TEntity">The type of the entity associated to the current operation.</typeparam>
public class RepositoryInterceptionContext<TEntity> where TEntity : class
{
/// <summary>
/// Gets the entity associated with the current operation.
/// </summary>
public TEntity Entity { get; }

/// <summary>
/// Gets the context.
/// </summary>
public IRepositoryContext Context { get; }

/// <summary>
/// Initializes a new instance of the <see cref="RepositoryInterceptionContext{TEntity}"/> class.
/// </summary>
/// <param name="entity">The entity.</param>
/// <param name="context">The context.</param>
public RepositoryInterceptionContext([NotNull] TEntity entity, [NotNull] IRepositoryContext context)
{
Entity = Guard.NotNull(entity, nameof(entity));
Context = Guard.NotNull(context, nameof(context));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,48 @@ public abstract class RepositoryInterceptorBase : IRepositoryInterceptor
/// An activity method which is executed when adding an entity to the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
public virtual void AddExecuting<TEntity>(TEntity entity) { }
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
public virtual void AddExecuting<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext) where TEntity : class {}

/// <summary>
/// An activity method which is executed when deleting an entity from the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
public virtual void DeleteExecuting<TEntity>(TEntity entity) { }
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
public virtual void DeleteExecuting<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext) where TEntity : class {}

/// <summary>
/// An activity method which is executed when updating an entity in the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
public virtual void UpdateExecuting<TEntity>(TEntity entity) { }
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
public virtual void UpdateExecuting<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext) where TEntity : class {}

/// <summary>
/// Asynchronously an activity method which is executed when adding an entity to the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
public virtual Task AddExecutingAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken()) => Task.FromResult(0);
public virtual Task AddExecutingAsync<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext, CancellationToken cancellationToken = new CancellationToken()) where TEntity : class => Task.FromResult(0);

/// <summary>
/// Asynchronously an activity method which is executed when deleting an entity from the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
public virtual Task DeleteExecutingAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken()) => Task.FromResult(0);
public virtual Task DeleteExecutingAsync<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext, CancellationToken cancellationToken = new CancellationToken()) where TEntity : class => Task.FromResult(0);

/// <summary>
/// Asynchronously an activity method which is executed when updating an entity in the repository.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entity">The entity.</param>
/// <param name="interceptionContext">The interception context which includes information for the current operation.</param>
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
public virtual Task UpdateExecutingAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken()) => Task.FromResult(0);
public virtual Task UpdateExecutingAsync<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext, CancellationToken cancellationToken = new CancellationToken()) where TEntity : class => Task.FromResult(0);
}
}
54 changes: 36 additions & 18 deletions src/DotNetToolkit.Repository/RepositoryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1430,10 +1430,11 @@ public void Add([NotNull] TEntity entity)

InterceptError(() => Guard.NotNull(entity, nameof(entity)));

Intercept(x => x.AddExecuting(entity));

UseContext(context =>
{
Intercept(x => x.AddExecuting(
new RepositoryInterceptionContext<TEntity>(entity, context)));

context.Add(entity);
context.SaveChanges();
});
Expand All @@ -1457,7 +1458,8 @@ public void Add([NotNull] IEnumerable<TEntity> entities)
{
foreach (var entity in entities)
{
Intercept(x => x.AddExecuting(entity));
Intercept(x => x.AddExecuting(
new RepositoryInterceptionContext<TEntity>(entity, context)));

context.Add(entity);
}
Expand All @@ -1480,10 +1482,11 @@ public void Update([NotNull] TEntity entity)

InterceptError(() => Guard.NotNull(entity, nameof(entity)));

Intercept(x => x.UpdateExecuting(entity));

UseContext(context =>
{
Intercept(x => x.UpdateExecuting(
new RepositoryInterceptionContext<TEntity>(entity, context)));

context.Update(entity);
context.SaveChanges();
});
Expand All @@ -1507,7 +1510,8 @@ public void Update([NotNull] IEnumerable<TEntity> entities)
{
foreach (var entity in entities)
{
Intercept(x => x.UpdateExecuting(entity));
Intercept(x => x.UpdateExecuting(
new RepositoryInterceptionContext<TEntity>(entity, context)));

context.Update(entity);
}
Expand All @@ -1530,10 +1534,11 @@ public void Delete([NotNull] TEntity entity)

InterceptError(() => Guard.NotNull(entity, nameof(entity)));

Intercept(x => x.DeleteExecuting(entity));

UseContext(context =>
{
Intercept(x => x.DeleteExecuting(
new RepositoryInterceptionContext<TEntity>(entity, context)));

context.Remove(entity);
context.SaveChanges();
});
Expand Down Expand Up @@ -1591,7 +1596,8 @@ public void Delete([NotNull] IEnumerable<TEntity> entities)
{
foreach (var entity in entities)
{
Intercept(x => x.DeleteExecuting(entity));
Intercept(x => x.DeleteExecuting(
new RepositoryInterceptionContext<TEntity>(entity, context)));

context.Remove(entity);
}
Expand Down Expand Up @@ -2175,10 +2181,12 @@ Task<int> Getter() =>
cancellationToken.ThrowIfCancellationRequested();
});

await InterceptAsync(x => x.AddExecutingAsync(entity, cancellationToken));

await UseContextAsync(async context =>
{
await InterceptAsync(x => x.AddExecutingAsync(
new RepositoryInterceptionContext<TEntity>(entity, context),
cancellationToken));

context.Add(entity);
await context.SaveChangesAsync(cancellationToken);
});
Expand Down Expand Up @@ -2209,7 +2217,9 @@ await UseContextAsync(async context =>
{
foreach (var entity in entities)
{
await InterceptAsync(x => x.AddExecutingAsync(entity, cancellationToken));
await InterceptAsync(x => x.AddExecutingAsync(
new RepositoryInterceptionContext<TEntity>(entity, context),
cancellationToken));

context.Add(entity);
}
Expand Down Expand Up @@ -2239,10 +2249,12 @@ await UseContextAsync(async context =>
cancellationToken.ThrowIfCancellationRequested();
});

await InterceptAsync(x => x.UpdateExecutingAsync(entity, cancellationToken));

await UseContextAsync(async context =>
{
await InterceptAsync(x => x.UpdateExecutingAsync(
new RepositoryInterceptionContext<TEntity>(entity, context),
cancellationToken));

context.Update(entity);
await context.SaveChangesAsync(cancellationToken);
});
Expand Down Expand Up @@ -2273,7 +2285,9 @@ await UseContextAsync(async context =>
{
foreach (var entity in entities)
{
await InterceptAsync(x => x.UpdateExecutingAsync(entity, cancellationToken));
await InterceptAsync(x => x.UpdateExecutingAsync(
new RepositoryInterceptionContext<TEntity>(entity, context),
cancellationToken));

context.Update(entity);
}
Expand Down Expand Up @@ -2303,10 +2317,12 @@ await UseContextAsync(async context =>
cancellationToken.ThrowIfCancellationRequested();
});

await InterceptAsync(x => x.DeleteExecutingAsync(entity, cancellationToken));

await UseContextAsync(async context =>
{
await InterceptAsync(x => x.DeleteExecutingAsync(
new RepositoryInterceptionContext<TEntity>(entity, context),
cancellationToken));

context.Remove(entity);
await context.SaveChangesAsync(cancellationToken);
});
Expand Down Expand Up @@ -2377,7 +2393,9 @@ await UseContextAsync(async context =>
{
foreach (var entity in entities)
{
await InterceptAsync(x => x.DeleteExecutingAsync(entity, cancellationToken));
await InterceptAsync(x => x.DeleteExecutingAsync(
new RepositoryInterceptionContext<TEntity>(entity, context),
cancellationToken));

context.Remove(entity);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public TestRepositoryTimeStampInterceptor(string loggedInUser)
_user = loggedInUser;
}

public override void AddExecuting<TEntity>(TEntity entity)
public override void AddExecuting<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext)
{
if (entity is IHaveTimeStamp haveStamp)
if (interceptionContext.Entity is IHaveTimeStamp haveStamp)
{
var currentTime = DateTime.UtcNow;

Expand All @@ -36,9 +36,9 @@ public override void AddExecuting<TEntity>(TEntity entity)
}
}

public override void UpdateExecuting<TEntity>(TEntity entity)
public override void UpdateExecuting<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext)
{
if (entity is IHaveTimeStamp haveStamp)
if (interceptionContext.Entity is IHaveTimeStamp haveStamp)
{
var currentTime = DateTime.UtcNow;

Expand All @@ -47,9 +47,9 @@ public override void UpdateExecuting<TEntity>(TEntity entity)
}
}

public override Task AddExecutingAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
public override Task AddExecutingAsync<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext, CancellationToken cancellationToken = new CancellationToken())
{
if (entity is IHaveTimeStamp haveStamp)
if (interceptionContext.Entity is IHaveTimeStamp haveStamp)
{
var currentTime = DateTime.UtcNow;

Expand All @@ -62,9 +62,9 @@ public override void UpdateExecuting<TEntity>(TEntity entity)
return Task.FromResult(0);
}

public override Task UpdateExecutingAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
public override Task UpdateExecutingAsync<TEntity>(RepositoryInterceptionContext<TEntity> interceptionContext, CancellationToken cancellationToken = new CancellationToken())
{
if (entity is IHaveTimeStamp haveStamp)
if (interceptionContext.Entity is IHaveTimeStamp haveStamp)
{
var currentTime = DateTime.UtcNow;

Expand Down
Loading

0 comments on commit 9cd5939

Please sign in to comment.