/// <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)));
 }
Example #4
0
 /// <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)));
 }
Example #5
0
        /// <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));
        }