ich möchte, zur vereinfachung von Linq2SAQL-Includes, eine Methode schreiben, welche alle Properties einer Entity als Expression zurückgibt. Dabei sollen auch auf Navigationseingeschaften zugegriffen werden (für Eager-Loading).
Als Beispiel soll folgender Code dienen (nicht sinnvoll, ich weiss)
public class Person
{
public Person()
{
Adresses= new List<Adress>();
}
public string Name { get; set; }
public int Age { get; set; }
public IList<Adress> Adresses { get; set; }
public IList<string> Names { get; set; }
public City City { get; set; }
}
public class Adress
{
public string Street { get; set; }
}
public class City
{
public string Name { get; set; }
public IList<string> Plz { get; set; }
}
Als Ergebnis würde ich mir dann eben Wünschen:
entity => entity.Adresses;
entity => entity.City;
entity => entity.City.Plz;
folgenden Code habe ich:
public class PropertyExtractor
{
public IEnumerable<Expression> GetNavigationProperties<T>(T entity, int level)
{
var entityType = entity.GetType();
var result = GetNavigationPropertiesInternal(entityType, level, 0);
return result;
}
public IEnumerable<Expression> GetNavigationPropertiesInternal(Type entityType, int maxDepth, int currentDepth)
{
var result = new List<Expression>();
foreach (var propertyInfo in entityType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType == typeof(string))
continue;
//here we have to concat the parent-accessor
var parameter = Expression.Parameter(entityType, "entity");
var property = Expression.Property(parameter, propertyInfo);
var funcType = typeof(Func<,>).MakeGenericType(entityType, propertyInfo.PropertyType);
var lambda = Expression.Lambda(funcType, property, parameter);
if (currentDepth ≤ maxDepth)
{
Type type = ListArgumentOrSelf(propertyInfo.PropertyType);
foreach (var info in GetNavigationPropertiesInternal(type, maxDepth, currentDepth++))
result.Add(info);
}
result.Add(lambda);
}
return result;
}
public Type ListArgumentOrSelf(Type type)
{
if (!type.IsGenericType)
return type;
if (type.GetGenericTypeDefinition() != typeof(IEnumerable<>) && !typeof(IEnumerable).IsAssignableFrom(type))
throw new Exception("Only IEnumerable<T> are allowed");
return type.GetGenericArguments()[0];
}
}
allerdings komme ich da nur auf die erste Ebene, nciht auf die 2te:
entity => entity.City.Plz.
HAt jemand eine Idee für mich?
Danke =)
mfg
Serial