/// <summary> /// Returns an instance of a resource repository accessor for a Has Many relationship. /// </summary> /// <typeparam name="TEntity">The type of entity to return.</typeparam> /// <param name="relationship">The relationship that defines the accessor to return.</param> /// <returns>The resource repository accessor instance.</returns> Func <IDatabase, IRepositoryAccessor <TEntity> > CreateHasManyAccessor <TEntity>(IHasManyRelationship relationship) { var propertyName = GuessDatabasePropertyName(typeof(TEntity)); return(CreateRepositoryAccessorFactory <TEntity>(propertyName, $"GetBy{GuessForeignKeyPropertyName(relationship)}Async")); }
/// <summary> /// Returns the name of the foreign key for the relationship. /// </summary> /// <param name="relationship">The relationship to guess the name of the foreign key from.</param> /// <returns>The name of the foreign key property.</returns> string GuessForeignKeyPropertyName(IHasManyRelationship relationship) { var inverse = relationship.Inverse(ContractResolver) as IBelongsToRelationship; return(inverse?.BackingField?.Name); }
/// <summary> /// Returns an instance of a resource repository accessor for a Has Many relationship. /// </summary> /// <typeparam name="TEntity">The type of entity to return.</typeparam> /// <param name="relationship">The relationship that defines the accessor to return.</param> /// <returns>The resource repository accessor instance.</returns> public Func <IDatabase, IRepositoryAccessor <TEntity> > GetOrCreateHasManyAccessor <TEntity>(IHasManyRelationship relationship) { return((Func <IDatabase, IRepositoryAccessor <TEntity> >)_cache.GetOrAdd(relationship, r => CreateHasManyAccessor <TEntity>((IHasManyRelationship)r))); }
/// <summary> /// Get or create an instance of a has many resource accessor. /// </summary> /// <typeparam name="TSource">The type of the source resource to enrich.</typeparam> /// <typeparam name="TDestination">The type of the destination resource that is enriched on the source.</typeparam> /// <param name="relationship">The relationship to create the accessor for.</param> /// <returns>The has many resource accessor.</returns> public IHasManyResourceAccessor <TSource, TDestination> GetOrCreateHasManyAccessor <TSource, TDestination>(IHasManyRelationship relationship) { return((IHasManyResourceAccessor <TSource, TDestination>)_cache.GetOrAdd(relationship, r => CreateHasManyAccessor <TSource, TDestination>((IHasManyRelationship)r))); }
/// <summary> /// Get or create an instance of a has many resource accessor. /// </summary> /// <typeparam name="TSource">The type of the source resource to enrich.</typeparam> /// <typeparam name="TDestination">The type of the destination resource that is enriched on the source.</typeparam> /// <param name="relationship">The relationship to create the accessor for.</param> /// <returns>The has many resource accessor.</returns> IHasManyResourceAccessor <TSource, TDestination> CreateHasManyAccessor <TSource, TDestination>(IHasManyRelationship relationship) { var sourceParameter = Expression.Parameter(typeof(TSource)); var destinationParameter = Expression.Parameter(typeof(TDestination)); var destinationEnumerableParameter = Expression.Parameter(typeof(IEnumerable <TDestination>)); var constructor = typeof(List <TDestination>).GetConstructor(new[] { typeof(IEnumerable <TDestination>) }); return(new DelegatingHasManyResourceAccessor <TSource, TDestination>( Expression .Lambda <Func <TDestination, int> >( Expression.PropertyOrField( destinationParameter, GuessForeignKeyPropertyName(relationship)), destinationParameter) .Compile(), Expression .Lambda <Action <TSource, IEnumerable <TDestination> > >( Expression.Assign( Expression.PropertyOrField( sourceParameter, relationship.Name), Expression.Convert( Expression.New(constructor, destinationEnumerableParameter), typeof(IReadOnlyList <TDestination>))), sourceParameter, destinationEnumerableParameter) .Compile())); }
/// <summary> /// Create a belongs to enricher for the given relationship. /// </summary> /// <param name="relationship">The relationship to create the enricher from.</param> /// <param name="database">The database to perform the enrichment within.</param> /// <returns>The enricher for the given resource and relationship.</returns> IResourceEnricher <TSource, TDestination> CreateHasManyEnricher <TSource, TDestinationEntity, TDestination>(IHasManyRelationship relationship, IDatabase database) where TSource : IEntityWithId where TDestinationEntity : IEntityWithId where TDestination : IEntityWithId { var foreignKeyAccessor = _resourceAccessorFactory.GetOrCreateHasManyAccessor <TSource, TDestination>(relationship); var repositoryAccessorFactory = _repositoryAccessorFactory.GetOrCreateHasManyAccessor <TDestinationEntity>(relationship); return(new DelegatingHasManyResourceEnricher <TSource, TDestinationEntity, TDestination>( foreignKeyAccessor, repositoryAccessorFactory(database))); }
/// <summary> /// Create a has many enricher for the given relationship. /// </summary> /// <typeparam name="TSource">The resource type to create the enricher for.</typeparam> /// <typeparam name="TDestination">The resource type on the other end of the relationship that is being enriched from.</typeparam> /// <param name="relationship">The relationship to create the enricher from.</param> /// <param name="database">The database to perform the enrichment within.</param> /// <returns>The enricher for the given resource and relationship.</returns> IResourceEnricher <TSource, TDestination> CreateHasManyEnricher <TSource, TDestination>(IHasManyRelationship relationship, IDatabase database) { var parameters = new[] { Expression.Parameter(typeof(IHasManyRelationship)), Expression.Parameter(typeof(IDatabase)) }; var methodCallExpression = Expression.Call( Expression.Constant(this), nameof(CreateHasManyEnricher), new[] { typeof(TSource), relationship.RelatedTo.BaseType, relationship.RelatedTo }, // ReSharper disable once CoVariantArrayConversion parameters); var @delegate = Expression .Lambda <Func <IHasManyRelationship, IDatabase, IResourceEnricher <TSource, TDestination> > >( methodCallExpression, parameters) .Compile(); return(@delegate(relationship, database)); }