为类型 T 定义的用户存储列表 Expressions/Lambdas

Store List of user defined Expressions/Lambdas for type T

这里的objective是为了让API消费者注册他们的模型以及如何从该模型中提取数据。使用下面的 ValueMapper,我们提供了一个 CreateMap 方法,该方法注册地图名称和调用函数以将数据检索为对象。

这里的想法是某些模型需要做更多的工作才能正确地输出数据。使用 CreateMap 注册模型后,我们会将其存储在内部 list/dictionary 中以供将来查找。我已经尝试了几个不同的角度来解决这个问题,这非常接近但仍然缺乏,因为调用者无法提供实际的表达式逻辑然后只能 return 一个直接值。

我已经将代码精简到最基本的部分,如果有更好的方法来解决我的问题,我愿意接受建议。

// static class that I would like to hold a list of 'expressions' that can be looked up and executed multuples times by the run time logic
public static class ValueMapper
{
    private static Dictionary<string, LambdaExpression> _rules = new Dictionary<string, LambdaExpression>();

    public static void CreateMap<T>(string ruleName, Expression<Func<T, object>> valueExpression)
    {
        _rules.Add(ruleName, valueExpression);
    }
}

public class Consumer
{
    public Consumer()
    {
        // This works but doesn't allow for registering further logic
        ValueMapper.CreateMap<ExternalUser>("foo", user => user.FirstName);

        // This has a compiler error as follows : "A lambda expression with a statement body cannot be converted to an expression tree"
        ValueMapper.CreateMap<ExternalUser>("foo", user =>
        {
            return user.FirstName + user.LastName;
        });
    }
}

// some external class
public class ExternalUser
{
    public string FirstName
    {
        get;
        set;
    }
    public string LastName
    {
        get;
        set;
    }
}

根据你的描述,你似乎不需要表达式,简单的委托应该做:

public static class ValueMapper {
    private static Dictionary<string, Func<object, object>> _rules = new Dictionary<string, Func<object, object>>();

    public static void CreateMap<T>(string ruleName, Func<T, object> valueFunc) {
        _rules.Add(ruleName, c => valueFunc((T) c));
    }
}

如果每个目标类型只有一个映射 - 无需使用字符串,请使用类型:

public static class ValueMapper {
    private static Dictionary<Type, Func<object, object>> _rules = new Dictionary<Type, Func<object, object>>();

    public static void CreateMap<TFrom, TTo>(Func<TFrom, TTo> valueFunc) {
        _rules.Add(typeof(TFrom), c => valueFunc((TFrom)c));
    }

    public static object Map<T>(T instance) {
        if (_rules.ContainsKey(typeof(T)))
            return _rules[typeof(T)](instance);
        // or throw here, or return null, depending on what you need
        return instance;
    }
}

如果您知道要映射到的类型 - 使用它们:

public static class ValueMapper {
    private static Dictionary<Type, Func<object, object>> _rules = new Dictionary<Type, Func<object, object>>();

    public static void CreateMap<TFrom, TTo>(Func<TFrom, TTo> valueFunc) {
        _rules.Add(typeof(TFrom), c => valueFunc((TFrom)c));
    }

    public static TTo Map<TTo>(object instance) {
        if (_rules.ContainsKey(instance.GetType()))
            return (TTo) _rules[instance.GetType()](instance);
        // throw here if necessary 
        return default(TTo);
    }
}