I want to make a C# Dictionary in which the key is the string name of a static property in a class and the value is the value of the property. Given a static property in the class called MyResources.TOKEN_ONE, how can I get the at the name of the property rather than its value? I only care about the end part of the property name (e.g. "TOKEN_ONE").
I've edited this to mention that I don't want to map all property values in the Dictionary, just a small subset of everything that's in the class. So assume that I want to get the name for a single property. Given MyResources.TOKEN_ONE, I want to get back "MyResources.TOKEN_ONE" or just "TOKEN_ONE".
Here's some sample code that shows what I'm trying to do. I need the property name because I'm trying to generate a javascript variable in which I map the property name to the variable name and the property value to the variable value. For example, I want the C# Dictionary to generate lines like the one below:
var TOKEN_ONE = "One";
using System;
using System.Collections.Generic;
namespace MyConsoleApp
{
class Program
{
static void Main(string[] args)
{
Dictionary<String, String> kvp = new Dictionary<String, String>();
// How can I use the name of static property in a class as the key for the dictionary?
// For example, I'd like to do something like the following where 'PropertyNameFromReflection'
// is a mechanism that would return "MyResources.TOKEN_ONE"
kvp.Add(MyResources.TOKEN_ONE.PropertyNameFromReflection, MyResources.TOKEN_ONE);
kvp.Add(MyResources.TOKEN_TWO.PropertyNameFromReflection, MyResources.TOKEN_TWO);
Console.ReadLine();
}
}
public static class MyResources
{
public static string TOKEN_ONE
{
get { return "One"; }
}
public static string TOKEN_TWO
{
get { return "Two"; }
}
}
}
If all you want is just to be able to refer to a single, specific property in one place in the code without having to refer to it by a literal string, then you can use an expression tree. For example, the following code declares a method that turns such an expression tree into a PropertyInfo object:
public static PropertyInfo GetProperty(Expression<Func<string>> expr)
{
var member = expr.Body as MemberExpression;
if (member == null)
throw new InvalidOperationException("Expression is not a member access expression.");
var property = member.Member as PropertyInfo;
if (property == null)
throw new InvalidOperationException("Member in expression is not a property.");
return property;
}
Now you can do something like this:
public void AddJavaScriptToken(Expression<Func<string>> propertyExpression)
{
var p = GetProperty(propertyExpression);
_javaScriptTokens.Add(p.Name, (string) p.GetValue(null, null));
}
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(() => Tokens.TOKEN_ONE);
AddJavaScriptToken(() => Tokens.TOKEN_TWO);
}
Here is a function that will get you the names of all static properties in a given type.
public static IEnumerable<string> GetStaticPropertyNames(Type t) {
foreach ( var prop in t.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ) {
yield return prop.Name;
}
}
If you want to build up the map of all property names to their values you can do the following
public static Dictionary<string,object> GetStaticPropertyBag(Type t) {
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var map = new Dictionary<string,object>();
foreach ( var prop in t.GetProperties(flags) ) {
map[prop.Name] = prop.GetValue(null,null);
}
return map;
}
Now you can call it with the following
var bag = GetStaticPropertyBag(typeof(MyResources));
You can accomplish this with reflection. The easiest way to get the property names is to loop over all of them.
foreach(var propInfo in this.GetType().GetProperties()) {
var name = propInfo.Name;
var value = propInfo.GetValue(this, null);
}
See GetProperties() and GetValue() for more specifics.
Well, I'm reluctantly answering my own question because I don't think it's possible to do this for a single static property. Ultimately, I ended up hard-coding the key in the Dictionary using a cut-and-paste of the property name. Here's what I ended up with:
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(Token.FOOBAR_TITLE, "FOOBAR_TITLE");
}
And here's the rest of the code:
protected Dictionary<String, String> _javaScriptTokens = new Dictionary<String, String>();
public void AddJavaScriptToken(string tokenValue, string propertyName)
{
_javaScriptTokens.Add(propertyName, tokenValue);
}
protected override void OnPreRender(EventArgs e)
{
if (_javaScriptTokens.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<String, String> kvp in _javaScriptTokens)
{
sb.AppendLine(String.Format("var TOKEN_{0} = unescape('{1}');", kvp.Key, PUtilities.Escape(kvp.Value)));
}
ClientScript.RegisterStartupScript(this.GetType(), "PAGE_TOKENS", sb.ToString(), true);
}
base.OnPreRender(e);
}
I hate having to use cut-and-paste hard-coding to keep the property name and the key in sync...Oh well...
Other answers have already explained how you can get a list of the static properties via Reflection. You said you don’t want all of them, only a subset of them. It seems, therefore, that you need a way to distinguish the properties you want from the ones you don’t want. One way to do this is using custom attributes.
Declare a custom attribute class:
[AttributeUsage(AttributeTargets.Property)]
public class WantThisAttribute : Attribute { }
Add this custom attribute to the properties you want:
public static class MyResources
{
[WantThis]
public static string TOKEN_ONE { get { return "One"; } }
[WantThis]
public static string TOKEN_TWO { get { return "Two"; } }
public static string DontWantThis { get { return "Nope"; } }
}
Iterate over the properties to find the ones you want:
public static Dictionary<string, object> GetStaticPropertyBag(Type t)
{
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var map = new Dictionary<string, object>();
foreach (var prop in t.GetProperties(flags))
if (prop.IsDefined(typeof(WantThisAttribute), true))
map[prop.Name] = prop.GetValue(null,null);
return map;
}
Related
The following code is used to search a class object's properties for a text match.
I call it like so:
ClassPropertyTextSearchOrig<UserViewModel>.FullTextSearchInit();
if (FullTextSearch<UserViewModel>.Match((UserViewModel)item, searchValue))
{
matchedItems.Add(item);
}
Class Property Search:
public static class ClassPropTextSearch<T>
{
private static List<Func<T, string>> _properties;
public static void FullTextSearchInit()
{
_properties = GetPropertyFunctions().ToList();
}
public static IEnumerable<Func<T, string>> GetPropertyFunctions()
{
var stringProperties = GetStringPropertyFunctions();
return stringProperties;
}
public static IEnumerable<Func<T, string>> GetStringPropertyFunctions()
{
var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty)
.Where(p => p.PropertyType == typeof(string)).ToList();
var properties = propertyInfos.Select(GetStringPropertyFunc);
return properties;
}
public static Func<T, string> GetStringPropertyFunc(PropertyInfo propInfo)
{
ParameterExpression x = System.Linq.Expressions.Expression.Parameter(typeof(T), "x");
Expression<Func<T, string>> expression = System.Linq.Expressions.Expression.Lambda<Func<T, string>>(System.Linq.Expressions.Expression.Property(x, propInfo), x);
Func<T, string> propertyAccessor = expression.Compile();
return propertyAccessor;
}
public static bool Match(T item, string searchTerm)
{
bool match = _properties.Select(prop => prop(item)).Any(value => value != null && value.ToLower().Contains(searchTerm.ToLower()));
return match;
}
}
What I'd like to do is make it more dynamic, so that I can just pass the object's Type in and not hard-code the Object T.
Getting rid of the T and passing the Type in, is fine. But if I'm doing it like this, can someone help me with creating an efficient process. This may have tens of thousands of objects to iterate through. I'm a little lost as of how to start. Can I still save time by initializing some of it?
[EDIT]
This piece of code show how I get a list of property names that are bound to columns in a DataGrid. This is done each time there is a search as column order may change.
string binding_path = "";
var columnBoundProperties = new List<KeyValuePair<int, string>>();
//Gets list of column bound properties and their display index
foreach (var col in datagrid.Columns.Where(c => c.Visibility == System.Windows.Visibility.Visible))
{
var binding = (col as DataGridBoundColumn).Binding as Binding;
binding_path = binding.Path.Path;
columnBoundProperties.Add(new KeyValuePair<int, string>(col.DisplayIndex, binding.Path.Path));
}
ClassPropTextSearch.Init(datagrid.Items[0].GetType(), columnBoundProperties)
var itemsSource = datagrid.Items as IEnumerable;
foreach (var item in itemsSource)
{
int column_index_match = ClassPropTextSearch.FirstPropMatch(item, searchValue);
if (column_index_match != null)
{
//Do something
break;
}
//else continue searching items
}
As far as the object search goes I would still like to keep initialization side of things, so here is the mockup of that
public static class ClassPropTextSearch
{
private static Type _itemType;
private static List<KeyValuePair<int, PropertyInfo>> _stringProperties = new List<KeyValuePair<int, PropertyInfo>>();
public static void init(Type itemType, List<KeyValuePair<int, string>> binding_properties)
{
_itemType = itemType;
foreach (var prop in binding_properties)
{
PropertyInfo propertyInfo = _itemType.GetProperty(prop.Value);
if (propertyInfo != null)
{
if (propertyInfo.PropertyType == typeof(string))
{
_stringProperties.Add(new KeyValuePair<int, PropertyInfo>(prop.Key, propertyInfo));
}
}
}
}
public static bool Match(object item, string searchTerm)
{
return PropertiesMatch(item, searchTerm).Any();
}
public static string FirstPropMatch(object item, string searchTerm)
{
//return int index of first property match
}
private static IEnumerable<PropertyInfo> PropertiesMatch(object item, string searchTerm)
{
//return list of matches
}
}
Try the following version, major changes:
No need to pass in generic type explicitly
Store the list of string properties of the target type
EDIT: Support to find the first matching property's name
public static class ClassPropTextSearch
{
private static Dictionary<Type, List<PropertyInfo>> _stringProperties =
new Dictionary<Type, List<PropertyInfo>>();
public static bool Match(object item, string searchTerm)
{
return PropertiesMatch(item, searchTerm).Any();
}
public static string FirstPropMatch(object item, string searchTerm)
{
var prop = PropertiesMatch(item, searchTerm).FirstOrDefault();
return prop != null ? prop.Name : string.Empty;
}
private static IEnumerable<PropertyInfo> PropertiesMatch(object item, string searchTerm)
{
// null checking skipped...
if (!_stringProperties.ContainsKey(item.GetType()))
{
// Retrieve and store the list of string properties of the input's type
var stringProperties = item.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty)
.Where(p => p.PropertyType == typeof(string))
.ToList();
_stringProperties.Add(item.GetType(), stringProperties);
}
return _stringProperties[item.GetType()]
.Where(prop => prop.GetValue(item, null) != null &&
((string)prop.GetValue(item, null)).ToLower().Contains(searchTerm.ToLower()));
}
}
Usage is now simplified to:
if (ClassPropTextSearch.Match(item, searchValue))
{
matchedItems.Add(item);
}
Do it all transparently.
Don't pass in the Type - instead, just pass in the object you want to investigate. You can get the Type by calling GetType().
Then, in your helper class (the one that does the searching) have a singleton Dictionary (or ConcurrentDictionary) which will key off the Type of the class to a class you create. Your class will look something like this (and will be immutable):
class StringProps
{
PropertyInfo[] m_infos;
}
So now you have a list of StringPropertyInfo[] you create the same way you do in your code. (If the StringProps is missing in your Dictionary, you simply create it and add it). That way you have cached versions of all your properties and you can just use them to grab the relevant text strings off your object..
A few notes:
This simplistic approach is cool if you have a finite set of types you interrogate in this fashion. If your app generates types dynamically, this will be an ever-growing memory hog (though, to be fair, since you cannot unload dynamically created types, it almost doesn't matter).
If performance is still an issue after you do this, you may need to resort to emitting code that accesses the property and not via reflection. This can be done by utilizing System.Linq.Expressions and specifically System.Linq.Expressions.LambdaExpression which will allow you to create a delegate that takes an object and casts it to the correct type, calling the correct property (thus not going thru reflection).
I need to access something like strClassname.strPropertyName I will have different values for strClassname and strProperty name in program execution.
Please direct me in right way.
Sounds to me like you are trying to get (or set) the value of a property on an object at runtime. So here's the most basic way to do this:
public static object GetPropertyValue(object instance, string strPropertyName)
{
Type type = instance.GetType();
System.Reflection.PropertyInfo propertyInfo = type.GetProperty(strPropertyName);
return propertyInfo.GetValue(instance, null);
}
... and to set a value:
public static void SetPropertyValue(object instance, string strPropertyName, object newValue)
{
Type type = instance.GetType();
System.Reflection.PropertyInfo propertyInfo = type.GetProperty(strPropertyName);
propertyInfo.SetValue(instance, newValue, null);
}
If you're attempting to get the names of properties of a class, here's a function for that:
public static IEnumerable<string> GetPropertyNames(string className)
{
Type type = Type.GetType(className);
return type.GetProperties().Select(p => p.Name);
}
Say that you have 100 objects, and you want to get the value of the Name property on each of them, here's a function that will do that:
public static IEnumerable<String> GetNames(IEnumerable<Object> objects, string nameProperty = "Name")
{
foreach (var instance in objects)
{
var type = instance.GetType();
var property = type.GetProperty(nameProperty);
yield return property.GetValue(instance, null) as string;
}
}
You can use reflection:
To get names of properties for a specific type use method Type.GetProperties. Method returns array of PropertyInfo objects and the property names are available through PropertyInfo.Name property. If you want to get only subset of all properties (e.g. only public static ones) use BindingFlags when calling GetProperties method. You have to specify at least two flags, one from Public/NonPublic and one of Instance/Static flags. If you use GetProperties without a BindingFlags parameter, default flags are Public + NonPublic + Instance.
Following example shows how to get public static properties.
using System.Reflection; // reflection namespace
// get all public static properties of MyClass type
PropertyInfo[] propertyInfos;
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public |
BindingFlags.Static);
// sort properties by name
Array.Sort(propertyInfos,
delegate(PropertyInfo propertyInfo1, PropertyInfo propertyInfo2)
{ return propertyInfo1.Name.CompareTo(propertyInfo2.Name); });
// write property names
foreach (PropertyInfo propertyInfo in propertyInfos)
{
Console.WriteLine(propertyInfo.Name);
}
[Source]
if there's a hundred or so classes and you know you want to access a specific property on each and you know every class will be instantiated, you should definitely consider creating an interface holding the property you wish to access ex.
public interface INamed
{
Name { get; }
}
Example usage:
var namedInstances = listOfClasses.Of<INamed>().Cast<INamed>();
foreach(var instance in namedInstances)
{
var name = instance.Name;
}
On the other hand, if you're not planning to instantiate these classes, you could try the following approach instead if the 'Name' property is static or const:
public interface INamed { } //Marker interface
public static class GetNamedHelper
{
private static IEnumerable<Type> GetAssemblyTypes(IEnumerable<Assembly> assemblies)
{
if (assemblies == null) yield break;
foreach (var assembly in assemblies.Where(assembly => assembly != null))
{
IEnumerable<Type> types;
try
{
types = assembly.GetTypes().Where(t => t != null);
}
catch (ReflectionTypeLoadException rtle)
{
types = rtle.Types.Where(t => t != null);
}
foreach (var type in types)
yield return type;
}
}
private static readonly Type namedMarkerInterface = typeof (INamed);
public static IEnumerable<string> GetNames(params Assembly[] assemblies)
{
var types = GetAssemblyTypes(assemblies)
.Where(t => t.GetInterfaces().Any(intf => intf == namedMarkerInterface));
foreach (var type in types)
{
//ex. public static string Name
var prop = type.GetProperty("Name", BindingFlags.Public | BindingFlags.Static);
if (prop == null || !prop.CanRead) continue;
yield return prop.GetValue(null, null) as string;
//ex. public const string Name
var field = type.GetField("Name", BindingFlags.Public);
if (field == null || !field.IsStatic) continue;
yield return field.GetValue(null) as string;
}
}
}
Eitherway, you need to know which classes to check and for what.
This question already has answers here:
Get property value from string using reflection
(24 answers)
Closed 4 years ago.
What I'm trying to do is setting the value of the property in a class using a string. For example, my class has the following properties:
myClass.Name
myClass.Address
myClass.PhoneNumber
myClass.FaxNumber
All the fields are of string type so I know ahead of time that it's always a string. Now, I want to be able to set the properties using a string as you could do with a DataSet object. Something like this:
myClass["Name"] = "John"
myClass["Address"] = "1112 River St., Boulder, CO"
Ideally, I want to just assign a variable and then set the property using that string name from the variable:
string propName = "Name"
myClass[propName] = "John"
I was reading about reflection and maybe it's the way to do it but I'm not sure how to go about setting that up while keeping the property access intact in the class. I want to still be able to use:
myClass.Name = "John"
Any code examples would be really great.
You can add indexer property, a pseudocode:
public class MyClass
{
public object this[string propertyName]
{
get
{
// probably faster without reflection:
// like: return Properties.Settings.Default.PropertyValues[propertyName]
// instead of the following
Type myType = typeof(MyClass);
PropertyInfo myPropInfo = myType.GetProperty(propertyName);
return myPropInfo.GetValue(this, null);
}
set
{
Type myType = typeof(MyClass);
PropertyInfo myPropInfo = myType.GetProperty(propertyName);
myPropInfo.SetValue(this, value, null);
}
}
}
You can add an indexer to your class and use reflection to aces the properties:
using System.Reflection;
public class MyClass {
public object this[string name]
{
get
{
var properties = typeof(MyClass)
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties)
{
if (property.Name == name && property.CanRead)
return property.GetValue(this, null);
}
throw new ArgumentException("Can't find property");
}
set {
return;
}
}
}
May be something like this?
public class PropertyExample
{
private readonly Dictionary<string, string> _properties;
public string FirstName
{
get { return _properties["FirstName"]; }
set { _properties["FirstName"] = value; }
}
public string LastName
{
get { return _properties["LastName"]; }
set { _properties["LastName"] = value; }
}
public string this[string propertyName]
{
get { return _properties[propertyName]; }
set { _properties[propertyName] = value; }
}
public PropertyExample()
{
_properties = new Dictionary<string, string>();
}
}
I want to make a C# Dictionary in which the key is the string name of a static property in a class and the value is the value of the property. Given a static property in the class called MyResources.TOKEN_ONE, how can I get the at the name of the property rather than its value? I only care about the end part of the property name (e.g. "TOKEN_ONE").
I've edited this to mention that I don't want to map all property values in the Dictionary, just a small subset of everything that's in the class. So assume that I want to get the name for a single property. Given MyResources.TOKEN_ONE, I want to get back "MyResources.TOKEN_ONE" or just "TOKEN_ONE".
Here's some sample code that shows what I'm trying to do. I need the property name because I'm trying to generate a javascript variable in which I map the property name to the variable name and the property value to the variable value. For example, I want the C# Dictionary to generate lines like the one below:
var TOKEN_ONE = "One";
using System;
using System.Collections.Generic;
namespace MyConsoleApp
{
class Program
{
static void Main(string[] args)
{
Dictionary<String, String> kvp = new Dictionary<String, String>();
// How can I use the name of static property in a class as the key for the dictionary?
// For example, I'd like to do something like the following where 'PropertyNameFromReflection'
// is a mechanism that would return "MyResources.TOKEN_ONE"
kvp.Add(MyResources.TOKEN_ONE.PropertyNameFromReflection, MyResources.TOKEN_ONE);
kvp.Add(MyResources.TOKEN_TWO.PropertyNameFromReflection, MyResources.TOKEN_TWO);
Console.ReadLine();
}
}
public static class MyResources
{
public static string TOKEN_ONE
{
get { return "One"; }
}
public static string TOKEN_TWO
{
get { return "Two"; }
}
}
}
If all you want is just to be able to refer to a single, specific property in one place in the code without having to refer to it by a literal string, then you can use an expression tree. For example, the following code declares a method that turns such an expression tree into a PropertyInfo object:
public static PropertyInfo GetProperty(Expression<Func<string>> expr)
{
var member = expr.Body as MemberExpression;
if (member == null)
throw new InvalidOperationException("Expression is not a member access expression.");
var property = member.Member as PropertyInfo;
if (property == null)
throw new InvalidOperationException("Member in expression is not a property.");
return property;
}
Now you can do something like this:
public void AddJavaScriptToken(Expression<Func<string>> propertyExpression)
{
var p = GetProperty(propertyExpression);
_javaScriptTokens.Add(p.Name, (string) p.GetValue(null, null));
}
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(() => Tokens.TOKEN_ONE);
AddJavaScriptToken(() => Tokens.TOKEN_TWO);
}
Here is a function that will get you the names of all static properties in a given type.
public static IEnumerable<string> GetStaticPropertyNames(Type t) {
foreach ( var prop in t.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ) {
yield return prop.Name;
}
}
If you want to build up the map of all property names to their values you can do the following
public static Dictionary<string,object> GetStaticPropertyBag(Type t) {
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var map = new Dictionary<string,object>();
foreach ( var prop in t.GetProperties(flags) ) {
map[prop.Name] = prop.GetValue(null,null);
}
return map;
}
Now you can call it with the following
var bag = GetStaticPropertyBag(typeof(MyResources));
You can accomplish this with reflection. The easiest way to get the property names is to loop over all of them.
foreach(var propInfo in this.GetType().GetProperties()) {
var name = propInfo.Name;
var value = propInfo.GetValue(this, null);
}
See GetProperties() and GetValue() for more specifics.
Well, I'm reluctantly answering my own question because I don't think it's possible to do this for a single static property. Ultimately, I ended up hard-coding the key in the Dictionary using a cut-and-paste of the property name. Here's what I ended up with:
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(Token.FOOBAR_TITLE, "FOOBAR_TITLE");
}
And here's the rest of the code:
protected Dictionary<String, String> _javaScriptTokens = new Dictionary<String, String>();
public void AddJavaScriptToken(string tokenValue, string propertyName)
{
_javaScriptTokens.Add(propertyName, tokenValue);
}
protected override void OnPreRender(EventArgs e)
{
if (_javaScriptTokens.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<String, String> kvp in _javaScriptTokens)
{
sb.AppendLine(String.Format("var TOKEN_{0} = unescape('{1}');", kvp.Key, PUtilities.Escape(kvp.Value)));
}
ClientScript.RegisterStartupScript(this.GetType(), "PAGE_TOKENS", sb.ToString(), true);
}
base.OnPreRender(e);
}
I hate having to use cut-and-paste hard-coding to keep the property name and the key in sync...Oh well...
Other answers have already explained how you can get a list of the static properties via Reflection. You said you don’t want all of them, only a subset of them. It seems, therefore, that you need a way to distinguish the properties you want from the ones you don’t want. One way to do this is using custom attributes.
Declare a custom attribute class:
[AttributeUsage(AttributeTargets.Property)]
public class WantThisAttribute : Attribute { }
Add this custom attribute to the properties you want:
public static class MyResources
{
[WantThis]
public static string TOKEN_ONE { get { return "One"; } }
[WantThis]
public static string TOKEN_TWO { get { return "Two"; } }
public static string DontWantThis { get { return "Nope"; } }
}
Iterate over the properties to find the ones you want:
public static Dictionary<string, object> GetStaticPropertyBag(Type t)
{
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var map = new Dictionary<string, object>();
foreach (var prop in t.GetProperties(flags))
if (prop.IsDefined(typeof(WantThisAttribute), true))
map[prop.Name] = prop.GetValue(null,null);
return map;
}
I have a project in which I have to get all the variables from a struct in a different class and add all their names to a combo box in a form. My primary issue at the moment is iterating through the struct in a way that I can add each variable individually to the combo box. I tried doing this:
msgVars vars = new msgVars();
foreach (object obj in vars)
{
comboBox1.Items.Add(GetName(obj));
}
but as you probably know, you can't iterate through a struct that way. Is there any way I can do this without hardcoding the variables in?
Also, for reference, this is the GetName function:
static string GetName<T>(T item) where T : struct
{
var properties = typeof(T).GetProperties();
if (properties.Length == 1)
{
return properties[0].Name;
}
else
{
return null;
}
}
If you are looking for a way to access properties of a struct (or class) at runtime without predefining in code that set of properties, what you probably need to use is reflection.
Here's an example:
struct MyStruct
{
private readonly int m_Age;
private readonly string m_LastName;
private readonly string m_FirstName;
public int Age { get { return m_Age; } }
public string LastName { get { return m_LastName; } }
public string FirstName { get { return m_FirstName; } }
public MyStruct( int age, string last, string first )
{
m_Age = age;
m_LastName = last;
m_FirstName = first;
}
}
class StructReflection
{
public static void Main(string[] args)
{
var theStruct = new MyStruct( 40, "Smith", "John" );
PrintStructProperties( theStruct );
}
public static void PrintStructProperties( MyStruct s )
{
// NOTE: This code will not handle indexer properties...
var publicProperties = s.GetType().GetProperties();
foreach (var prop in publicProperties)
Console.WriteLine( "{0} = {1}", prop.Name, prop.GetValue( s, null ) );
}
}
You could try using Reflection. How about storing the information in a Hashtable.
public Hashtable GetPropertyInfo(Person person)
{
var properties = new Hashtable();
PropertyInfo[] propInfo = person.GetType().GetProperties();
foreach (PropertyInfo prop in propInfo)
{
properties.Add(prop.Name, prop.GetValue(person, null));
}
return properties;
}
Then you could write the information out via:
var person = new Person()
Person.Name = "Test";
Person.Age = 21;
var PropertyInfo = GetPropertyInfo(person);
foreach (string key in PropertyInfo.Keys)
{
Console.WriteLine("{0} = {1}", key, PropertyInfo[key]);
}
A struct is a single entity, not a collection of variables. This means that you can't 'iterate' over its properties. What you need to do is get a collection of the property names and iterate over it. Your GetName function can't do this because it just returns the name of the first property.
To add the property names to a combo all you have to do is:
var vars = new msgVars();
foreach(var name in GetNames(vars))
comboBox1.Items.Add(name);
In fact, getting the property name is so easy that you could get rid of GetNames completley and just write
foreach (var prop in typeof(msgVars).GetProperties())
comboBox1.Items.Add(prop.Name);
There are various ways you can write GetNames to return a collection of names. You can fill a List with the property names although the simplest is to have it return an iterator like this:
public static IEnumerable<string> GetNames<T>(T obj) where T:struct
{
var properties = typeof (T).GetProperties();
foreach (var propertyInfo in properties)
{
yield return propertyInfo.Name;
}
}
Finally, you don't really need to pass an instance of your struct to the method, as you are enumerating the structs property names, not their values. You can rewrite GetNames like this
public static IEnumerable<string> GetNames<T>() where T:struct
{
var properties = typeof (T).GetProperties();
foreach (var propertyInfo in properties)
{
yield return propertyInfo.Name;
}
}
and load the names like this
foreach(var name in GetNames<msgVars>())
comboBox1.Items.Add(name);