English 中文(简体)
AutoMapper for Func s between selectedor category
原标题:AutoMapper for Func s between selector types
  • 时间:2011-09-15 00:14:44
  •  标签:
  • c#
  • linq
最佳回答

Here s a solution using AutoMapper:

Func<Cat, bool> GetMappedSelector(Func<Dog, bool> selector)
{
    Func<Cat, Dog> mapper = Mapper.CreateMapExpression<Cat, Dog>().Compile();
    Func<Cat, bool> mappedSelector = cat => selector(mapper(cat));
    return mappedSelector;
}

<><>UPDATE: 这是我第一次回答以来的1.5年,我今天在我的回答中看到了扩大,因为人们正在问,在你有代表而不是代表时如何这样做。

原则上,解决办法相同——我们需要能够compose 。 这两项职能(selectormapper)合并为单一职能。 不幸的是,由于在C#中没有任何东西可以“召唤”另一个表达方式(如我们与代表一样),我们可以在法典中直接体现这一点。 例如,以下法典将无法编纂:

Expression<Func<Cat, bool>> GetMappedSelector(Expression<Func<Dog, bool>> selector)
{
    Expression<Func<Cat, Dog>> mapper = Mapper.CreateMapExpression<Cat, Dog>();
    Expression<Func<Cat, bool>> mappedSelector = cat => selector(mapper(cat));
    return mappedSelector;
}

因此,创建我们组成职能的唯一途径是利用<条码>System.Linq.Expressions课程建立http://msdn.microsoft.com/en-us/library/bb3951%7928v=vs.90%29.aspx>expression 树我们自己。

我们确实需要修改<代码> > > > > > <> > > > > > > > > > > > ...... > > ...... > ...... > ...... ...... ...... 这将成为我们的新陈词典,即:<>>>>>>>。

为了替换参数一,创建了一个子级:http://msdn.microsoft.com/en-us/library/bb882521%28v=vs.90%29.aspx>ExpressionVisitor。 能够tra树和用任意表述取代单一参数的类别:

class ParameterReplacer : ExpressionVisitor
{
    private ParameterExpression _parameter;
    private Expression _replacement;

    private ParameterReplacer(ParameterExpression parameter, Expression replacement)
    {
        _parameter = parameter;
        _replacement = replacement;
    }

    public static Expression Replace(Expression expression, ParameterExpression parameter, Expression replacement)
    {
        return new ParameterReplacer(parameter, replacement).Visit(expression);
    }

    protected override Expression VisitParameter(ParameterExpression parameter)
    {
        if (parameter == _parameter)
        {
            return _replacement;
        }
        return base.VisitParameter(parameter);
    }
}

然后,我制定了一种延伸方法,即Compose(),该方法利用访问者来编造两个拉姆布达语,一个外语和一个内语:

public static class FunctionCompositionExtensions
{
    public static Expression<Func<X, Y>> Compose<X, Y, Z>(this Expression<Func<Z, Y>> outer, Expression<Func<X, Z>> inner)
    {
        return Expression.Lambda<Func<X ,Y>>(
            ParameterReplacer.Replace(outer.Body, outer.Parameters[0], inner.Body),
            inner.Parameters[0]);
    }
}

现在,随着所有基础设施的建立,我们可以修改我们的<代码>GetMappedSelector()方法,使用我们的<代码>Compose(的延伸:

Expression<Func<Cat, bool>> GetMappedSelector(Expression<Func<Dog, bool>> selector)
{
    Expression<Func<Cat, Dog>> mapper = Mapper.CreateMapExpression<Cat, Dog>();
    Expression<Func<Cat, bool>> mappedSelector = selector.Compose(mapper);
    return mappedSelector;
}

我创建了一个,用于测试这方面的情况。 我希望,我的解释不会被过分混淆;但不幸的是,几乎没有一种更简单的做法来做你重新努力做的事情。 如果你仍然被完全混淆,至少你可以重新使用我的法典,并赞赏处理 expression树的微妙和复杂性!

问题回答

@luksan, 感谢激励! 你的解决办法没有解决我的问题,但我想到了。 由于我需要把翻译的表述传递给我。 OrderBy(),在使用内部压抑翻译方法时,就做了工作。 但是,我提出解决办法,处理这两个案件,也更简单地加以执行。 这种方法也是通用的,可再用于任何测绘类型。 该守则是:

private Expression<Func<TDestination, TProperty>> GetMappedSelector<TSource, TDestination, TProperty>(Expression<Func<TSource, TProperty>> selector)
{
    var map = Mapper.FindTypeMapFor<TSource, TDestination>();

    var mInfo = ReflectionHelper.GetMemberInfo(selector);

    if (mInfo == null)
    {
        throw new Exception(string.Format(
            "Can t get PropertyMap. "{0}" is not a member expression", selector));
    }

    PropertyMap propmap = map
        .GetPropertyMaps()
        .SingleOrDefault(m => 
            m.SourceMember != null && 
            m.SourceMember.MetadataToken == mInfo.MetadataToken);

    if (propmap == null)
    {
        throw new Exception(
            string.Format(
            "Can t map selector. Could not find a PropertyMap for {0}", selector.GetPropertyName()));
    }

    var param = Expression.Parameter(typeof(TDestination));
    var body = Expression.MakeMemberAccess(param, propmap.DestinationProperty.MemberInfo);
    var lambda = Expression.Lambda<Func<TDestination, TProperty>>(body, param);

    return lambda;
}

这里是《思考手册法》(只是为了将守则置于更清洁的之上而使用)

private static class ReflectionHelper
{
    public static MemberInfo GetMemberInfo(Expression memberExpression)
    {
        var memberExpr = memberExpression as MemberExpression;

        if (memberExpr == null && memberExpression is LambdaExpression)
        {
            memberExpr = (memberExpression as LambdaExpression).Body as MemberExpression;
        }

        return memberExpr != null ? memberExpr.Member : null;
    }
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签