Моя основная задача - создать динамическую группу и использовать ее в NHibernate.
Рассмотрим этот нединамический пример, который работает :
_repository.Collection<User>().GroupBy(u => new { u.Active }).Select(s => s.Key, Count = s.Count())
Теперь,Я создаю динамический объект для динамического генерирования части new { u.Active }
:
private Expression<Func<T, object>> CreateGrouping<T>(IEnumerable<string> by)
{
var dynamicTypeForGroup = GetDynamicTypeForGroup<T>(by);
var sourceItem = Expression.Parameter(typeof(T));
var bindings = dynamicTypeForGroup
.GetFields()
.Select(p => Expression.Bind(p, Expression.PropertyOrField(sourceItem, p.Name)))
.Cast<MemberBinding>()
.ToArray();
return Expression.Lambda<Func<T, object>>(Expression.Convert(
Expression.MemberInit(
Expression.New(dynamicTypeForGroup.GetConstructor(Type.EmptyTypes)),
bindings),
dynamicTypeForGroup),
sourceItem);
}
Тип генерируется в методе GetDynamicTypeForGroup
, а затем создается с помощью Expression.MemberInit(Expression.New(dynamicTypeForGroup.GetConstructor(Type.EmptyTypes)), bindings)
Вот как типгенерируется:
private Type GetDynamicTypeForGroup<T>(IEnumerable<string> members)
{
var type = typeof(T);
var dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName(Guid.NewGuid().ToString()),
AssemblyBuilderAccess.RunAndSave
);
var dynamicModule = dynamicAssembly.DefineDynamicModule(Guid.NewGuid().ToString());
var typeBuilder = dynamicModule.DefineType(Guid.NewGuid().ToString());
var properties = members.Select(prop => type.GetProperty(ObjectExtensions.NormilizePropertyName(prop)))
.Where(prop => prop != null)
.Cast<MemberInfo>();
var fields = properties
.Select(property => typeBuilder.DefineField(
property.Name,
((PropertyInfo)property).PropertyType,
FieldAttributes.Public
)).Cast<FieldInfo>()
.ToArray();
GenerateEquals(typeBuilder, fields);
GenerateGetHashCode(typeBuilder, fields);
return typeBuilder.CreateType();
}
ТАК, ПРОБЛЕМА
Если я использую _repository.Collection<User>().GroupBy(u => new { u.Active })
, это работает, но если я добавляю часть Выбрать - .Select(s => s.Key, Count = s.Count())
(или любой другой выбранный устав)) Я получил следующее NotSupportedException: MemberInit
System.NotSupportedException: MemberInit em NHibernate.Linq.Visitors.HqlGeneratorExpressionVisitor.VisitExpression (выражение-выражение) (опущено выражение)
*
Я сомневаюсь:
- Я знаю, что NHibernate поддерживает оператор Select с группой по и анонимным типом, но почему он не может поддержать Select, еслиэтот тип был создан с помощью дерева выражений?