I'm trying to create dynamic selector where it's assign properties that is declared in target class. This function even go deeply in to the object and do the same thing, it's selecting properties that's in target class. But i can't figure out how i create Select-ToList within the Select.
I need to create SelectToList for RestAvailForRest.
I have the code that make selector for object and even select with in the object i need same thing but for list in object.
Here is Select that c# create [1]: https://i.stack.imgur.com/8yt40.png
I need same thing but dynamic function
Here is my function:
public static Expression<Func<TSource, TSelect>> DynamicSelectGenerator<TSource, TSelect>()
{
string[] EntityFields = typeof(TSource).GetProperties().Select(propertyInfo => propertyInfo.Name).ToArray();
NewExpression xNew = Expression.New(typeof(TSelect));
ParameterExpression xParameter = Expression.Parameter(typeof(TSource), "s");
List<string> selectorProperties = typeof(TSelect).GetTypeInfo().DeclaredFields.Select(s => s.Name.Replace(">k__BackingField", string.Empty).Replace("<", string.Empty)).ToList();
List<MemberAssignment> bindings = EntityFields
.Where(w => typeof(TSource).GetProperties().ToList().Where(ww => ww.Name == w).FirstOrDefault() != null && selectorProperties.Contains(w))
.Select(s =>
{
string[] xFieldAlias = s.Split(':');
string field = xFieldAlias[0];
string[] fieldSplit = field.Split('.');
PropertyInfo propertyInfoDb = typeof(TSource).GetProperties().ToList().Where(w => w.Name == field).FirstOrDefault();
PropertyInfo propertyInfoModel;
if (xFieldAlias.Length > 1)
{
propertyInfoModel = typeof(TSelect).GetProperty(xFieldAlias[1]);
}
else
{
propertyInfoModel = typeof(TSelect).GetProperties().Where(w => w.Name == field).FirstOrDefault();
}
MemberAssignment res = null;
// DbModelAttribute is just empty attribute
/*
public class DbModelAttribute : Attribute { }
*/
object targetDbAttr = propertyInfoModel.GetCustomAttributes(typeof(DbModelAttribute), false).FirstOrDefault();
if (targetDbAttr != null)
{
if (propertyInfoModel.PropertyType.IsGenericType)
{
// TODO: need your help here to create MemberAssignment as Select-ToList Expression.
}
else
{
NewExpression yNew = Expression.New(propertyInfoModel.PropertyType);
List<MemberAssignment> childBindins = null;
MemberInitExpression yInit = null;
PropertyInfo childDbPropInfo = typeof(TSource).GetProperties().ToList().Where(w => w.Name == field).FirstOrDefault();
MemberExpression childDbXParameter = Expression.Property(xParameter, childDbPropInfo);
BinaryExpression notEqualExpr = Expression.NotEqual(childDbXParameter, Expression.Constant(null, childDbPropInfo.PropertyType));
childBindins = GetChildrenMembers(propertyInfoModel.PropertyType, field, xParameter, typeof(TSource));
yInit = Expression.MemberInit(yNew, childBindins);
res = Expression.Bind(propertyInfoModel, yInit);
Expression conditionExpr1 = Expression.Condition(
notEqualExpr,
yInit,
Expression.Constant(null, typeof(TSelect).GetProperties().ToList().Where(w => w.Name == field).FirstOrDefault().PropertyType)
);
return Expression.Bind(propertyInfoModel, conditionExpr1);
}
}
else
{
MemberExpression xOriginal = Expression.Property(xParameter, propertyInfoDb);
res = Expression.Bind(propertyInfoModel, xOriginal);
}
return res;
}
).ToList();
bindings.DistinctObjectByRef(ref bindings, d => d.Member);
MemberInitExpression xInit = Expression.MemberInit(xNew, bindings);
Expression<Func<TSource, TSelect>> lambda = Expression.Lambda<Func<TSource, TSelect>>(xInit, xParameter);
return lambda;
static List<MemberAssignment> GetChildrenMembers(Type toType, string field, Expression xParameter, Type parentTypeDb)
{
List<PropertyInfo> toTypeProperties = toType.GetProperties().ToList().Where(w => w.DeclaringType == toType).ToList();
PropertyInfo parentDbParameter = parentTypeDb.GetProperties().ToList().Where(w => w.Name == field).FirstOrDefault();
return toTypeProperties.Select(s =>
{
MemberAssignment res;
PropertyInfo childDbParameter = parentDbParameter.PropertyType.GetProperty(s.Name);
List<PropertyInfo> toTypeProps = toType.GetProperties().ToList();
PropertyInfo childModelParameter = toTypeProps.Where(w => w.Name == s.Name).FirstOrDefault();
object targetDbAttr = childModelParameter.GetCustomAttributes(typeof(DbModelAttribute), false).FirstOrDefault();
MemberExpression childDbXParameter = Expression.Property(xParameter, parentDbParameter);
if (targetDbAttr != null)
{
NewExpression zNew = Expression.New(childModelParameter.PropertyType);
List<MemberAssignment> childBindins = GetChildrenMembers(childModelParameter.PropertyType, s.Name, childDbXParameter, parentDbParameter.PropertyType);
MemberInitExpression zInit = Expression.MemberInit(zNew, childBindins);
PropertyInfo childDbPropInfo = parentDbParameter.PropertyType.GetProperties().ToList().Where(w => w.Name == childModelParameter.Name).FirstOrDefault();
MemberExpression childDbZParameter = Expression.Property(childDbXParameter, childDbPropInfo);
BinaryExpression notEqualExpr = Expression.NotEqual(childDbZParameter, Expression.Constant(null, childModelParameter.PropertyType));
Expression conditionExpr1 = Expression.Condition(
notEqualExpr,
zInit,
Expression.Constant(null, childModelParameter.PropertyType)
);
res = Expression.Bind(childModelParameter, conditionExpr1);
}
else
{
MemberExpression childModelXParameter = Expression.Property(childDbXParameter, childDbParameter);
res = Expression.Bind(childModelParameter, childModelXParameter);
}
return res;
}).ToList();
}
}
Thanks.
Aucun commentaire:
Enregistrer un commentaire