using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Text; using Microsoft.Extensions.DependencyInjection; namespace AutoMapPropertyHelper { public interface IAutomappedAttribute { public virtual object ApplyTo(IServiceProvider? providers, object value) => throw new NotImplementedException(); public virtual object? ApplyFrom(IServiceProvider? providers, object source) => throw new NotImplementedException(); public virtual Type GetSourceType() => throw new NotImplementedException(); } public interface IAutomappedAttribute : IAutomappedAttribute { object IAutomappedAttribute.ApplyTo(IServiceProvider? providers, object value) => throw new NotImplementedException(); object? IAutomappedAttribute.ApplyFrom(IServiceProvider? providers, object source) => throw new NotImplementedException(); Type IAutomappedAttribute.GetSourceType() => throw new NotImplementedException(); public TSource ApplyTo(IServiceProvider? providers, TSource value); public TSelf ApplyFrom(IServiceProvider? providers, TSource source); public Expression> GetProjectorFrom(IServiceProvider providers) => throw new NotImplementedException(); } public interface IPolymorphicResponse : IAutomappedAttribute { public abstract TResponseType GetResponseType(TType entity); public abstract Dictionary GetProjectors(IServiceProvider providers); public Expression> GetCustomProjectorFrom(IServiceProvider providers) { // Parameter for the combined lambda var parameter = Expression.Parameter(typeof(TType), "x"); // Start building the expression tree dynamically Expression? resultExpression = null; foreach (var (type, projector) in GetProjectors(providers)) { // Condition: Check if the parameter is of the current type var typeCondition = Expression.TypeIs(parameter, type); // Cast the parameter to the current type var castedParameter = Expression.Convert(parameter, type); // Invoke the projector with the casted parameter var invokeProjector = Expression.Invoke(projector, castedParameter); // Convert the result to the common response type var convertedResult = Expression.Convert(invokeProjector, typeof(TResponseType)); // Combine with existing conditions (if any) resultExpression = resultExpression == null ? (Expression)convertedResult : Expression.Condition(typeCondition, convertedResult, resultExpression); } // Fallback for unsupported types resultExpression ??= Expression.Constant(null, typeof(TResponseType)); // Create the combined lambda var combinedProjector = Expression.Lambda>(resultExpression, parameter); return combinedProjector; } public TResponseType ApplyFrom(IServiceProvider? providers, TType source) { throw new NotImplementedException(); } public TType ApplyTo(IServiceProvider? providers, TType value) { throw new NotImplementedException(); } } }