寻找一种更简洁的方法将C#setter放入词典<&燃气轮机;用于映射

寻找一种更简洁的方法将C#setter放入词典<&燃气轮机;用于映射,c#,.net,reflection,C#,.net,Reflection,这是我正在处理的更大一部分代码的表示,这是一个映射器。最初它是作为一个大的switch语句编写的,但我更喜欢将映射作为一个表,而不是一个长的switch 我的第一次传球看起来像这样(来自LINQPad): 我真的不想在调用中作为带完全反射的字符串执行: { "one", "One" }, // No { "one", nameof(Foobar.One) }, // Real

这是我正在处理的更大一部分代码的表示,这是一个映射器。最初它是作为一个大的
switch
语句编写的,但我更喜欢将映射作为一个表,而不是一个长的
switch

我的第一次传球看起来像这样(来自LINQPad):

我真的不想在调用中作为带完全反射的字符串执行:

{ "one", "One" },                       // No
{ "one", nameof(Foobar.One) },          // Really, just no.
我似乎记得有一种更简洁的方法可以做到这一点,但我的谷歌fu让我失望。通过将签名更改为
Dictionary
,然后执行以下操作,我可以更简洁地找到getter:

   { "one", f.One }                        // The getter, not the setter.

但这并不能让我成为二传手。想法?

您可以这样定义映射:

Mapping<Foobar, decimal> foobarMapping = new Mapping<Foobar, decimal> 
{
    { "one", f => f.One },
    { "double", f => f.Two },
    { "tricycle", f => f.Three },
};

public class Foobar
{
    public decimal One { get; set; }
    public decimal Two { get; set; }
    public decimal Three { get; set; }
}

void Main()
{
    Foobar obj = new Foobar();
    obj.One = 100M;
    
    foobarMapping[obj, "one"].Dump();
    
    foobarMapping[obj, "tricycle"] = 400M;
    obj.Three.Dump();
}

class Mapping<TFrom, TTo>: IEnumerable<KeyValuePair<string, PropertyInfo>>
{
    Dictionary<string, PropertyInfo> mapping = new Dictionary<string, PropertyInfo>();
    
    public void Add(string name, Expression<Func<TFrom, TTo>> mappingFunction) =>
        mapping.Add(name, (PropertyInfo)((MemberExpression)mappingFunction.Body).Member);
        
    public TTo this[TFrom from, string key]
    {
        get => (TTo)mapping[key].GetValue(from);
        set => mapping[key].SetValue(from, value);
    }
        
    public IEnumerator<KeyValuePair<string, PropertyInfo>> GetEnumerator() =>
        mapping.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

您编写的内容看起来几乎像一个索引器,或者尝试在不使用
dynamic
或继承
DynamicObject
的情况下使用动态调用。您可以使用
x[“三轮车”]=100M
x.tricycle=100M
。这两种方法在性能上都比操作字典便宜。您可以使用类似于
(action)typeof(Foobar).GetProperty(“One”).SetMethod.CreateDelegate(typeof(action))
的设置程序,但它并不更加精确
   { "one", f.One }                        // The getter, not the setter.
Mapping<Foobar, decimal> foobarMapping = new Mapping<Foobar, decimal> 
{
    { "one", f => f.One },
    { "double", f => f.Two },
    { "tricycle", f => f.Three },
};

public class Foobar
{
    public decimal One { get; set; }
    public decimal Two { get; set; }
    public decimal Three { get; set; }
}

void Main()
{
    Foobar obj = new Foobar();
    obj.One = 100M;
    
    foobarMapping[obj, "one"].Dump();
    
    foobarMapping[obj, "tricycle"] = 400M;
    obj.Three.Dump();
}

class Mapping<TFrom, TTo>: IEnumerable<KeyValuePair<string, PropertyInfo>>
{
    Dictionary<string, PropertyInfo> mapping = new Dictionary<string, PropertyInfo>();
    
    public void Add(string name, Expression<Func<TFrom, TTo>> mappingFunction) =>
        mapping.Add(name, (PropertyInfo)((MemberExpression)mappingFunction.Body).Member);
        
    public TTo this[TFrom from, string key]
    {
        get => (TTo)mapping[key].GetValue(from);
        set => mapping[key].SetValue(from, value);
    }
        
    public IEnumerator<KeyValuePair<string, PropertyInfo>> GetEnumerator() =>
        mapping.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
100
400