/// <summary> /// Executes the pre action hooks, filtered by <paramref name="requiresValidation"/>. /// </summary> /// <param name="modifiedEntries">The modified entries to execute hooks for.</param> /// <param name="requiresValidation">if set to <c>true</c> executes hooks that require validation, otherwise executes hooks that do NOT require validation.</param> private void ExecutePreActionHooks(IEnumerable <HookedEntityEntry> modifiedEntries, bool requiresValidation) { foreach (var entityEntry in modifiedEntries) { var entry = entityEntry; //Prevents access to modified closure foreach (var hook in _ctx.PreHooks.Where(x => (x.HookStates & entry.PreSaveState) == entry.PreSaveState && x.RequiresValidation == requiresValidation)) { var metadata = new HookEntityMetadata(HookType.Pre, entityEntry, entityEntry.PreSaveState, _ctx.Context); hook.HookObject(entityEntry.Entity, metadata); if (metadata.HasStateChanged) { entityEntry.PreSaveState = metadata.State; } } if (!requiresValidation) { var hookedEntity = entry.Entity as IPreActionHook; if (hookedEntity != null) { var metadata = new HookEntityMetadata(HookType.Pre, entityEntry, entityEntry.PreSaveState, _ctx.Context); hookedEntity.HookObject(entry.Entity, metadata); } } } }
public void RunPostActionHooks() { var hasPostHooks = _ctx.PostHooks.Any(); // Save this to a local variable since we're checking this again later. if (hasPostHooks) { foreach (var entityEntry in _modifiedEntries) { var entry = entityEntry; var hookedEntity = entry.Entity as IPostActionHook; if (hookedEntity != null) { var metadata = new HookEntityMetadata(HookType.Post, entityEntry, entityEntry.PreSaveState, _ctx.Context); hookedEntity.HookObject(entry.Entity, metadata); } //Obtains hooks that 'listen' to one or more Entity States foreach (var hook in _ctx.PostHooks.Where(x => (x.HookStates & entry.PreSaveState) == entry.PreSaveState)) { var metadata = new HookEntityMetadata(HookType.Post, entityEntry, entityEntry.PreSaveState, _ctx.Context); hook.HookObject(entityEntry.Entity, metadata); } } } }
/// <summary> /// Executes the pre action hooks, filtered by <paramref name="requiresValidation"/>. /// </summary> /// <param name="modifiedEntries">The modified entries to execute hooks for.</param> /// <param name="requiresValidation">if set to <c>true</c> executes hooks that require validation, otherwise executes hooks that do NOT require validation.</param> private void ExecutePreActionHooks(IEnumerable<HookedEntityEntry> modifiedEntries, bool requiresValidation) { foreach (var entityEntry in modifiedEntries) { var entry = entityEntry; //Prevents access to modified closure foreach (var hook in _ctx.PreHooks.Where(x => (x.HookStates & entry.PreSaveState) == entry.PreSaveState && x.RequiresValidation == requiresValidation)) { var metadata = new HookEntityMetadata(HookType.Pre, entityEntry, entityEntry.PreSaveState, _ctx.Context); hook.HookObject(entityEntry.Entity, metadata); if (metadata.HasStateChanged) { entityEntry.PreSaveState = metadata.State; } } if (!requiresValidation) { var hookedEntity = entry.Entity as IPreActionHook; if (hookedEntity != null) { var metadata = new HookEntityMetadata(HookType.Pre, entityEntry, entityEntry.PreSaveState, _ctx.Context); hookedEntity.HookObject(entry.Entity, metadata); } } } }
/// <summary> /// Implements the interface. This causes the hook to only run for objects that are assignable to TEntity. /// </summary> public void HookObject(object entity, HookEntityMetadata metadata) { if (entity is TEntity) { Hook((TEntity)entity, metadata); } }
void IHook.HookObject(object entity, HookEntityMetadata metadata) { if (entity == null) { return; } List <PropertyInfo> changedProperties = null; if (metadata.Entry != null) { object res; if (metadata.Entry.Data.TryGetValue("DateTimeUtcPreActionHook_changedProperties", out res)) { changedProperties = (List <PropertyInfo>)res; } else { changedProperties = new List <PropertyInfo>(); metadata.Entry.Data["DateTimeUtcPreActionHook_changedProperties"] = changedProperties; } } var properties = metadata.HookType != HookType.Post ? entity.GetType().GetProperties() .Where(x => x.PropertyType == typeof(DateTime) || x.PropertyType == typeof(DateTime?)) : changedProperties; if (properties != null) { foreach (var property in properties) { var dt = property.PropertyType == typeof(DateTime?) ? (DateTime?)property.GetValue(entity) : (DateTime)property.GetValue(entity); if (dt == null) { continue; } if (metadata.HookType == HookType.Pre) { if (dt.Value.Kind == DateTimeKind.Utc) { property.SetValue(entity, dt.Value.ToLocalTime()); if (changedProperties != null) { changedProperties.Add(property); } } } } } }
void IHook.HookObject(object entity, HookEntityMetadata metadata) { if (entity == null) return; List<PropertyInfo> changedProperties = null; if (metadata.Entry != null) { object res; if (metadata.Entry.Data.TryGetValue("DateTimeUtcPreActionHook_changedProperties", out res)) { changedProperties = (List<PropertyInfo>) res; } else { changedProperties = new List<PropertyInfo>(); metadata.Entry.Data["DateTimeUtcPreActionHook_changedProperties"] = changedProperties; } } var properties = metadata.HookType != HookType.Post ? entity.GetType().GetProperties() .Where(x => x.PropertyType == typeof(DateTime) || x.PropertyType == typeof(DateTime?)) : changedProperties; if (properties != null) { foreach (var property in properties) { var dt = property.PropertyType == typeof(DateTime?) ? (DateTime?)property.GetValue(entity) : (DateTime)property.GetValue(entity); if (dt == null) continue; if (metadata.HookType == HookType.Pre) { if (dt.Value.Kind == DateTimeKind.Utc) { property.SetValue(entity, dt.Value.ToLocalTime()); if (changedProperties != null) { changedProperties.Add(property); } } } } } }
public void HookObject(object entity, HookEntityMetadata metadata) { var e = entity as TEntity; if (e != null) { if (metadata.HookType == HookType.Pre) { HookBeforeSave(e, metadata.State == EntityState.Added, metadata); } else if (metadata.HookType == HookType.Post) { HookAfterSave(e, metadata.State == EntityState.Added, metadata); } } }
public void HookObject(object entity, HookEntityMetadata metadata) { var entityType = entity.GetType(); var props = _cache.GetOrAdd(entityType, t => entityType.GetProperties() .Where(pi => (Nullable.GetUnderlyingType(pi.PropertyType) != null ? pi.PropertyType.GetGenericArguments()[0] : pi.PropertyType) == typeof(DateTime)) .Select(pi => { var attr = pi.GetCustomAttribute<FillWithCurrentDateAttribute>(); return new Tuple<PropertyInfo, bool?>(pi, attr != null ? attr.OnCreateOnly : (bool?) null); }) .Where(x => x.Item2 != null) .Select(x => new Tuple<PropertyInfo, bool>(x.Item1, x.Item2.Value)) .ToArray()); foreach (var pi in props.Where(x => metadata.State == EntityState.Added || !x.Item2 && metadata.State == EntityState.Modified)) { pi.Item1.SetValue(entity, DateTime.Now); } }
public void HookObject(object entity, HookEntityMetadata metadata) { var currentUserId = Thread.CurrentPrincipal.Identity.GetUserId() ?? DefaultUserId; if (currentUserId != null) { var entityType = entity.GetType(); var props = _cache.GetOrAdd(entityType, t => entityType.GetProperties() .Where(pi => pi.PropertyType == typeof(string)) .Select(pi => { var attr = pi.GetCustomAttribute<FillWithCurrentUserAttribute>(); return new Tuple<PropertyInfo, bool?>(pi, attr != null ? attr.OnCreateOnly : (bool?) null); }) .Where(x => x.Item2 != null) .Select(x => new Tuple<PropertyInfo, bool>(x.Item1, x.Item2.Value)) .ToArray()); foreach (var pi in props.Where(x => metadata.State == EntityState.Added || !x.Item2 && metadata.State == EntityState.Modified)) { pi.Item1.SetValue(entity, currentUserId); } } }
/// <summary> /// The logic to perform per entity before the registered action gets performed. /// This gets run once per entity that has been changed. /// </summary> /// <param name="entity">The entity that is processed by Entity Framework.</param> /// <param name="metadata">Metadata about the entity in the context of this hook - such as state.</param> public abstract void Hook(TEntity entity, HookEntityMetadata metadata);
protected virtual void HookOnLoad(TEntity entity, HookEntityMetadata metadata) { }
protected virtual void HookAfterSave(TEntity entity, bool isNew, HookEntityMetadata metadata) { HookOnLoad(entity, metadata); }
protected virtual void HookBeforeSave(TEntity entity, bool isNew, HookEntityMetadata metadata) { }
public void HookObject(object entity, HookEntityMetadata metadata) { var entityId = entity as IEntityObjectId<string>; if (entityId != null && entityId.Id.IsEmpty()) entityId.Id = SequentialGuid.NewGuid().ToString(); }