例如,我想在此重载上动态调用 ProjectTo:
public static IQueryable ProjectTo(this IQueryable source, params Expression<Func<TDestination, object>>[] membersToExpand);
像这样
Expression.Call(typeof(AutoMapper.QueryableExtensions.Extensions), "ProjectTo", new[] { DtoType },'What goes here as arguments???')
这是我要调用的重载
public static MethodCallExpression Call(Type type, string methodName, Type[] typeArguments, params Expression[] arguments);
基于此链接: https ://github.com/AutoMapper/AutoMapper/issues/2234#event-1175181678
更新
当我有这样的参数时
IEnumerable<Expression> membersToExpand = new Expression<Func<TDto, object>>[] { };
并将其传递给这样的函数:
Expression.Call(typeof(Extensions), "ProjectTo", new[] { typeof(TDto) }, body, Expression.Constant(membersToExpand));
但是,当membersToExpand参数为null时,它会抛出异常 No generic method 'ProjectTo' on type 'AutoMapper.QueryableExtensions.Extensions' 与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数
所以让我澄清一下问题:
'membersToExpand' 必须不为空(好吧,我知道),当它不为空时,'Expression.Call' 可以找到合适的重载并且它会成功但问题是当'membersToExpand' 为空时,我必须创建默认的“membersToExpand”,我必须动态创建它,我不能像这样创建它
Expression.Constant(null, typeof(Expression<Func<TDto, object>>[]))
如何动态创建:
typeof(Expression<Func<TDto, object>>[]
当我只知道'typeof(TDto)'时?
要重现问题只需复制并粘贴,然后运行:
class Program
{
static void Main(string[] args)
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<UserGroupDto, UserGroup>();
cfg.CreateMap<UserGroup, UserGroupDto>()
.ForMember(dest => dest.UserGroupDetails, conf =>
{
conf.MapFrom(ent => ent.UserGroupDetails);
conf.ExplicitExpansion();
});
cfg.CreateMap<UserGroupDetailDto, UserGroupDetail>();
cfg.CreateMap<UserGroupDetail, UserGroupDetailDto>()
.ForMember(dto => dto.UserGroupName, conf => conf.MapFrom(ent => ent.UserGroup.Title));
});
// Someone Wants To Call WITH Members To Expand
Start(new Expression<Func<UserGroupDto, object>>[] { e => e.UserGroupDetails });
Console.WriteLine("===============================================");
// Someone Wants To Call WITHOUT Members To Expand (It's a pain to pass an empty 'new Expression<Func<UserGroupDto, object>>[] { }' so it's better to create the default, dynamically when it's null )
Start(new Expression<Func<UserGroupDto, object>>[] { });
// Someone Wants To Call WITHOUT Members To Expand and pass it null and it will THROW Exception
// Start(null);
Console.ReadLine();
}
static void Start(IEnumerable<Expression> membersToExpand)
{
using (var db = new MyDbContext())
{
IEnumerable projected = CallProjectToDynamically(db.UserGroups.AsQueryable(), typeof(UserGroupDto), membersToExpand);
foreach (var item in projected.OfType<UserGroupDto>())
{
Console.WriteLine(" UserGroupID => " + item.ID);
Console.WriteLine(" UserGroupTitle => " + item.Title);
if (item.UserGroupDetails != null)
item.UserGroupDetails.ToList().ForEach(d =>
{
Console.WriteLine(" UserGroupDetailID => " + d.ID);
Console.WriteLine(" UserGroupDetailTitle => " + d.Title);
Console.WriteLine(" UserGroupDetailUserGroupName => " + d.UserGroupName);
});
}
}
}
static IQueryable CallProjectToDynamically<T>(IQueryable<T> source, Type dtoType, IEnumerable<Expression> membersToExpand)
{
// What i want is this:
// if(membersToExpand == null)
// Create The default dynamically For 'params Expression<Func<TDestination, object>>[] membersToExpand'
var param = Expression.Parameter(typeof(IQueryable<T>), "data");
var body = Expression.Call(typeof(Extensions), "ProjectTo", new[] { dtoType }, param, Expression.Constant(membersToExpand));
return (Expression.Lambda<Func<IQueryable<T>, IQueryable>>(body, param).Compile())(source);
}
}
public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name=MyDbContext")
{
Database.SetInitializer(new MyDbContextDBInitializer());
}
public virtual DbSet<UserGroup> UserGroups { get; set; }
public virtual DbSet<UserGroupDetail> UserGroupMembers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<UserGroup>()
.HasMany(e => e.UserGroupDetails)
.WithRequired(e => e.UserGroup)
.HasForeignKey(e => e.UserGroupID);
}
}
public class MyDbContextDBInitializer : DropCreateDatabaseAlways<MyDbContext>
{
protected override void Seed(MyDbContext context)
{
IList<UserGroup> defaultStandards = new List<UserGroup>
{
new UserGroup() { Title = "First UserGroup", UserGroupDetails = new [] { new UserGroupDetail { Title = "UGD for First UserGroup" } } },
new UserGroup() { Title = "Second UserGroup", UserGroupDetails = new [] { new UserGroupDetail { Title = "UGD for Second UserGroup" } } },
new UserGroup() { Title = "Third UserGroup", UserGroupDetails = new [] { new UserGroupDetail { Title = "UGD for Third UserGroup" } } }
};
foreach (UserGroup std in defaultStandards)
context.UserGroups.Add(std);
base.Seed(context);
}
}
public partial class UserGroup
{
public UserGroup()
{
UserGroupDetails = new HashSet<UserGroupDetail>();
}
public long ID { get; set; }
public string Title { get; set; }
public virtual ICollection<UserGroupDetail> UserGroupDetails { get; set; }
}
public partial class UserGroupDetail
{
public long ID { get; set; }
public long UserGroupID { get; set; }
public string Title { get; set; }
public virtual UserGroup UserGroup { get; set; }
}
public partial class UserGroupDto
{
public long ID { get; set; }
public string Title { get; set; }
public IEnumerable<UserGroupDetailDto> UserGroupDetails { get; set; }
}
public partial class UserGroupDetailDto
{
public long ID { get; set; }
public string Title { get; set; }
public long UserGroupID { get; set; }
public string UserGroupName { get; set; }
}
真挚地。