简体   繁体   中英

Dictionary mapping strings to properties

I have a class where I would like to return the value of various properties based on a string that I can define as an attribute like so:

    [FieldName("data_bus")]
    public string Databus
    {
        get { return _record.Databus; }
    }

So I would like a dictionary holding:

private static readonly IDictionary<string, Func<string>> PropertyMap;

Which is initialised here:

static MyClass()
    {
        PropertyMap = new Dictionary<string, Func<string>>();

        var myType = typeof(ArisingViewModel);

        foreach (var propertyInfo in myType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
        {
            if (propertyInfo.GetGetMethod() != null)
            {
                var attr = propertyInfo.GetCustomAttribute<FieldNameAttribute>();

                if (attr == null)
                    continue;

                PropertyInfo info = propertyInfo;
                PropertyMap.Add(attr.FieldName, () => info.Name);
                // Not sure what I'm doing here.
            }
        }
    }

And invoked somehow along the lines of:

   public static object GetPropertyValue(object obj, string field)
    {

        Func<string> prop;
        PropertyMap.TryGetValue(field, out prop);
        // return 
    }

Can anyone show me how to set this up? I'm not sure I properly understand how Func works.

you will need to change your dictionary definition so that the function will accept an instance of the class

private static readonly IDictionary<string, Func<ArisingViewModel,string>> PropertyMap;

Then you need your static initializer to be

static MyClass()
{
    PropertyMap = new Dictionary<string, Func<ArisingViewModel,string>>();

    var myType = typeof(ArisingViewModel);

    foreach (var propertyInfo in myType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
    {
        if (propertyInfo.GetGetMethod() != null)
        {
            var attr = propertyInfo.GetCustomAttribute<FieldNameAttribute>();

            if (attr == null)
                continue;

            PropertyInfo info = propertyInfo;
            PropertyMap.Add(attr.FieldName, obj => (string)info.GetValue(obj,null));
        }
    }
}

public static object GetPropertyValue(ArisingViewModel obj, string field)
{
    Func<ArisingViewModel,string> prop;
    if (PropertyMap.TryGetValue(field, out prop)) {
       return prop(obj);
    }
    return null; //Return null if no match
  }

You can also make your solution a little more generic if you wish.

public static MyClass<T> {

  private static readonly IDictionary<string, Func<T,string>> PropertyMap;


  static MyClass()
  {
    PropertyMap = new Dictionary<string, Func<T,string>>();

    var myType = typeof(T);

    foreach (var propertyInfo in myType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
    {
        if (propertyInfo.GetGetMethod() != null)
        {
            var attr = propertyInfo.GetCustomAttribute<FieldNameAttribute>();

            if (attr == null)
                continue;

            PropertyInfo info = propertyInfo;
            PropertyMap.Add(attr.FieldName, obj => (string)info.GetValue(obj,null));
        }
    }
  }

  public static object GetPropertyValue(T obj, string field)
  {
    Func<ArisingViewModel,string> prop;
    if (PropertyMap.TryGetValue(field, out prop)) {
       return prop(obj);
    }
    return null; //Return null if no match
  }
}

EDIT -- and to call the generic version you would do

var value = MyClass<ArisingViewModel>.GetPropertyValue(mymodel,"data_bus");

You are on the right track. See below with an example similar to what you have.

Dictionary<string, Func<string>> dic = new Dictionary<string, Func<string>>();
private void test()
{
    Button btn = new Button();
    btn.Text = "BlahBlah";
    dic.Add("Value", () => btn.Text);
}

private void test2()
{
    Func<string> outval;
    dic.TryGetValue("Value", out outval);
    MessageBox.Show(outval());
}

In the example test(), I define a new Button class and assign a value to its .Text property. Then I add a new entry into my Dictionary<>. In test2() I retrieve that Func and invoke it, which returns the string value of btn.Text.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM