为类型 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);
}
}
这里的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);
}
}