public RelatedDtoProperty(RelatedDtoAttribute attribute, RelatedValueType dtoType, RelatedValueType idType)
        {
            Attribute = attribute;
            DtoType   = dtoType;
            IdType    = idType;

            BuildDtoListType();
        }
Exemple #2
0
        private Dictionary <string, RelatedDtoProperty> BuildRules(Type targetDtoType)
        {
            var rules = new Dictionary <string, RelatedDtoProperty>();

            var propsForRelatedDto = targetDtoType.GetProperties()
                                     .Select(x => new { Property = x, RelatedDtoAttribute = (RelatedDtoAttribute)x.GetCustomAttribute(typeof(RelatedDtoAttribute), true) })
                                     .Where(x => x.RelatedDtoAttribute != null)
                                     .ToArray();

            foreach (var propForRelatedDto in propsForRelatedDto)
            {
                var attribute       = propForRelatedDto.RelatedDtoAttribute;
                var dtoProperty     = propForRelatedDto.Property;
                var dtoPropertyType = dtoProperty.PropertyType;

                RelatedValueType dtoType = new RelatedValueType(dtoProperty);

                string idPropertyName = attribute.IdPropertyName;

                var isList = dtoType.GenericType != null || dtoType.IsArray;

                if (idPropertyName == null)
                {
                    idPropertyName = (isList ? $"{dtoPropertyType.Name}Ids" : $"{dtoProperty.Name}Id");
                }

                PropertyInfo idProperty = null;

                if (!string.IsNullOrEmpty(idPropertyName))
                {
                    idProperty = _targetType.GetProperty(idPropertyName, BindingFlags.Public | BindingFlags.Instance);
                }

                if (idProperty == null && isList)
                {
                    throw new MissingIdPropertyNameException(targetDtoType.Name, dtoProperty.Name);
                }

                RelatedValueType idType = idProperty == null ? null : new RelatedValueType(idProperty);

                var rule = new RelatedDtoProperty(attribute, dtoType, idType);
                rules.Add(dtoProperty.Name, rule);
            }

            return(rules);
        }
Exemple #3
0
        private async Task InternalLoadDtoAsync <TTargetDto, TKeyProvider>(RelatedDtoProperty relatedProperty, RelatedValueType idType, IDtoLoadRule loaderRule, TTargetDto[] arrTargetDtos, TKeyProvider[] arrKeyProviders)
            where TTargetDto : class
            where TKeyProvider : class
        {
            var dtoType = relatedProperty.DtoType;

            var keyProviderWithIds = arrKeyProviders.ToDictionary(x => x, keyProvider => idType.Property.GetValue(keyProvider));
            var idsToLoad          = keyProviderWithIds.Values.Where(x => x != null).ToArray();

            Dictionary <object, object> dictLoadedDtos = null;

            if (idsToLoad.Any())
            {
                object[] relatedDtos = (await loaderRule.LoadAsObjectAsync(_serviceProvider, idsToLoad)).ToArray();
                dictLoadedDtos = relatedDtos.ToDictionary(x => loaderRule.GetKey(x), x => x);
            }

            for (var index = 0; index < arrTargetDtos.Length; index++)
            {
                var targetDto   = arrTargetDtos[index];
                var keyProvider = arrKeyProviders[index];

                object propValue = null;

                var desiredDtoKey = keyProviderWithIds[keyProvider];

                if (desiredDtoKey != null && dictLoadedDtos.ContainsKey(desiredDtoKey))
                {
                    propValue = dictLoadedDtos[desiredDtoKey];
                }

                dtoType.Property.SetValue(targetDto, propValue);
            }
        }
Exemple #4
0
        public async Task <IEnumerable <TTargetDto> > LoadListAsync <TTargetDto, TKeyProvider>(IEnumerable <TTargetDto> targetDtos, IEnumerable <TKeyProvider> keyProviders)
            where TTargetDto : class
            where TKeyProvider : class
        {
            var targetDtoType = typeof(TTargetDto);

            var relatedDtoProperties = _profile.GetRelatedDtoProperties(targetDtoType);

            if (relatedDtoProperties == null)
            {
                throw new UnsupportedTargetTypeException(targetDtoType);
            }

            var keyProviderType       = typeof(TKeyProvider);
            var isKeyProviderSameType = targetDtoType == keyProviderType;
            var arrTargetDtos         = targetDtos.ToArray();
            var arrKeyProviders       = keyProviders.ToArray();

            foreach (var relatedProperty in relatedDtoProperties)
            {
                var dtoType     = relatedProperty.DtoType;
                var dtoProperty = dtoType.Property;
                var attribute   = relatedProperty.Attribute;

                RelatedValueType idType = null;

                if (isKeyProviderSameType)
                {
                    idType = relatedProperty.IdType;
                }
                else
                {
                    if (dtoType.GenericType != null || dtoType.IsArray)
                    {
                        throw new MissingIdPropertyNameException(targetDtoType.Name, dtoProperty.Name);
                    }

                    var idProp = keyProviderType.GetProperty(attribute.IdPropertyName ?? dtoProperty.Name + "Id", BindingFlags.Public | BindingFlags.Instance);

                    if (idProp != null)
                    {
                        idType = new RelatedValueType(idProp);
                    }
                }

                if (idType == null)
                {
                    continue;
                }

                var loaderRule = _profile.GetRule(dtoType.ElementType);

                if (loaderRule == null)
                {
                    continue;
                }

                if (dtoType.GenericType != null)
                {
                    await InternalLoadDtoEnumerableAsync(relatedProperty, idType, loaderRule, arrTargetDtos, arrKeyProviders);
                }
                else if (dtoType.IsArray)
                {
                    await InternalLoadDtoArrayAsync(relatedProperty, idType, loaderRule, arrTargetDtos, arrKeyProviders);
                }
                else
                {
                    await InternalLoadDtoAsync(relatedProperty, idType, loaderRule, arrTargetDtos, arrKeyProviders);
                }
            }

            return(arrTargetDtos);
        }
Exemple #5
0
        private async Task InternalLoadDtoArrayAsync <TTargetDto, TKeyProvider>(RelatedDtoProperty relatedProperty, RelatedValueType idType, IDtoLoadRule loaderRule, TTargetDto[] arrTargetDtos, TKeyProvider[] arrKeyProviders)
            where TTargetDto : class
            where TKeyProvider : class
        {
            var dtoType = relatedProperty.DtoType;

            var keyProviderWithIds = arrKeyProviders.ToDictionary(x => x, keyProvider => ((IEnumerable)idType.Property.GetValue(keyProvider)).Cast <object>().ToArray());
            var idsToLoad          = keyProviderWithIds.Values.Where(x => x != null).SelectMany(x => x).Where(x => x != null).Distinct().ToArray();

            Dictionary <object, object> dictLoadedDtos = null;

            var dtoElementType = dtoType.ElementType;

            if (idsToLoad.Any())
            {
                object[] relatedDtos = (await loaderRule.LoadAsObjectAsync(_serviceProvider, idsToLoad)).ToArray();
                dictLoadedDtos = relatedDtos.ToDictionary(x => loaderRule.GetKey(x), x => x);
            }

            for (var index = 0; index < arrTargetDtos.Length; index++)
            {
                var targetDto   = arrTargetDtos[index];
                var keyProvider = arrKeyProviders[index];

                object propValue = null;

                var desiredDtoKeys = keyProviderWithIds[keyProvider];

                if (desiredDtoKeys != null)
                {
                    var dtoArray = Array.CreateInstance(dtoType.ElementType, desiredDtoKeys.Length);

                    for (int i = 0; i < desiredDtoKeys.Length; i++)
                    {
                        var desiredDtoKey = desiredDtoKeys[i];

                        object dto = null;

                        if (desiredDtoKey != null && dictLoadedDtos.ContainsKey(desiredDtoKey))
                        {
                            dto = dictLoadedDtos[desiredDtoKey];
                        }

                        dtoArray.SetValue(dto, i);
                    }

                    propValue = dtoArray;
                }

                dtoType.Property.SetValue(targetDto, propValue);
            }
        }