using System; using System.Linq; using Luticate2.Auth.Utils.Business.Fields; using Luticate2.Auth.Utils.Business.Utils; using Luticate2.Auth.Utils.Dbo; using Luticate2.Auth.Utils.Dbo.Fields; using Luticate2.Auth.Utils.Dbo.Result; using Luticate2.Auth.Utils.Interfaces; using Microsoft.Extensions.DependencyInjection; namespace Luticate2.Auth.Utils.Business.Converters.ObjectConverter { public class LuObjectConverterPoco : ILuObjectConverter { protected IServiceProvider ServiceProvider { get; } public LuObjectConverterPoco(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; } public LuResult Convert(object srcObj, object dstObj, LuFieldDbo path, LuPartialFieldsDbo fields, ILuObjectConverterOptions options) { if (srcObj == null) { return LuResult.Ok(default(TTypeTo)); } var typeTo = typeof(TTypeTo); var descriptor = ServiceProvider.GetService>(); if (descriptor == null) { return LuResult.Error(LuStatus.InternalError.ToInt(), $"Could not find converter descriptor for {typeTo} => {typeof(TTypeFrom)}"); } foreach (var memberInfo in typeTo.GetProperties()) { var memberPath = LuFieldDbo.Make(path).Add(memberInfo.Name); if (!fields.Fields.IsIncluded(memberPath)) { continue; } // TODO Hack to deal with inherited members; need to check if it is correct var originalMemberInfo = memberInfo.DeclaringType.GetMember(memberInfo.Name).First(); var subSrcPropExpressionResult = descriptor.GetMemberValueExpression(originalMemberInfo, options.DescriptorOptions); if (!subSrcPropExpressionResult) { return subSrcPropExpressionResult.To(); } var subSrcPropExpression = subSrcPropExpressionResult.Data; var subSrcPropDelegate = subSrcPropExpression.Compile(); var subSrcProp = subSrcPropDelegate.DynamicInvoke(srcObj); var subSrcType = subSrcProp != null ? subSrcProp.GetType() : subSrcPropExpression.ReturnType; var subDstType = memberInfo.GetUnderlyingType(); var objectConverterResult = LuObjectConverterUtils.GetObjectConverter(ServiceProvider, subSrcType, subDstType); if (!objectConverterResult) { return objectConverterResult.To(); } var objectConverter = objectConverterResult.Data; var subDstObjResult = options.Allocator.GetInstance(subDstType); if (!subDstObjResult) { return subDstObjResult.To(); } var subDstObj = subDstObjResult.Data; var dstPropResult = objectConverter.Convert(subSrcProp, subDstObj, memberPath, fields, options); if (!dstPropResult) { return dstPropResult; } var dstProp = dstPropResult.Data; var result = LuExpressionUtils.SetValueFromMember(memberInfo, dstObj, dstProp); if (!result) { return result.To(); } } return LuResult.Ok(dstObj); } } }