我有以下方法SetMapping()
,用于使用表达式定义一些映射设置。
public class AggregateMap<TDataEntity>
{
protected Expression<Func<IUpdateConfiguration<TDataEntity>, object>> graphMapping;
protected void SetMapping(Expression<Func<IUpdateConfiguration<TDataEntity>, object>> mapping)
{
graphMapping = mapping;
}
}
调用代码示例:
SetMapping(map => map.OwnedCollection(root => root.ChildEntities));
上面的方法效果很好,但我想通过提供 SetOwnedCollectionMapping()
进一步抽象该方法。这意味着调用代码可以提供更基本的表达式。
进一步抽象方法:
protected void SetOwnedCollectionMapping<T>(Expression<Func<TDataEntity, ICollection<T>>> mapping)
{
graphMapping = map => map.OwnedCollection<TDataEntity, T>(mapping);
}
调用代码示例:
SetOwnedCollectionMapping(root => root.ChildEntities);
然后,通过在 Entity Framework DbContext 实例上调用以下方法,在外部库 (RefactorThis.GraphDiff) 中使用此 graphMapping
字段:
public static void UpdateGraph<T>(this DbContext context, T entity, Expression<Func<IUpdateConfiguration<T>, object>> mapping) where T : class;
运行时抛出以下异常:
An exception of type 'System.InvalidCastException' occurred in RefactorThis.GraphDiff.dll but was not handled in user code
Additional information: Unable to cast object of type 'System.Reflection.RtFieldInfo' to type 'System.Reflection.PropertyInfo'.
我一定混淆了我的泛型类型,但我看不出新旧实现之间的区别。
这是 OwnedCollection
方法的签名:
public static IUpdateConfiguration<T> OwnedCollection<T, T2>(this IUpdateConfiguration<T> config, Expression<Func<T, System.Collections.Generic.ICollection<T2>>> expression);
编辑:向问题添加了UpdateGraph
信息。
最佳答案
两个实现之间的主要区别在于,第二个实现捕获方法参数,而第一个实现则不捕获。该参数作为字段存储在闭包中,并且该字段访问的存在可能会导致 RefactorThis.GraphDiff.dll
中出现问题。
尝试按如下方式更改第二个实现:
protected void SetOwnedCollectionMapping<T>(Expression<Func<TDataEntity, ICollection<T>>> mapping)
{
//
// Hack to resolve the `OwnedCollection` extension method.
//
Expression<Func<IUpdateConfiguration<TDataEntity>, object>> template =
_ => _.OwnedCollection(mapping);
var map = Expression.Parameter(
typeof(IUpdateConfiguration<TDataEntity>),
"map");
graphMapping = Expression.Lambda<Func<IUpdateConfiguration<TDataEntity>, object>>(
Expression.Call(
((MethodCallExpression)template.Body).Method,
map,
Expression.Quote(mapping)),
map);
}
graphMapping
的值应该与您的第一个实现生成的值相同。
关于c# - 通用表达式抽象问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21450933/