这里的目标是允许API使用者注册他们的模型以及如何从该模型中提取数据。使用下面的ValueMapper,我们提供了一个CreateMap方法,该方法注册要调用的地图名称和函数,以将数据作为对象进行检索。
这里的想法是某些模型有更多的工作来正确地获取数据。使用CreateMap注册模型后,我们会将其存储在内部列表/字典中以供将来查找。我已经尝试了几个不同的角度来解决这个问题,这是非常接近但仍然缺乏,因为调用者不能提供实际的表达式逻辑然后只能返回一个直接的值。
我已经将代码简化为裸露的骨头,如果有更好的方法来解决我的问题,我会接受建议。
// 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);
}
}