C# Accessing object properties indexer style - c#

Is there any tool,library that would allow me to access my objects properties indexer style ?
public class User
{
public string Name {get;set;}
}
User user = new User();
user.Name = "John";
string name = user["Name"];
Maybe the dynamic key word could help me here ?

You can use reflection to get property value by its name
PropertyInfo info = user.GetType().GetProperty("Name");
string name = (string)info.GetValue(user, null);
And if you want to use index for this you can try something like that
public object this[string key]
{
get
{
PropertyInfo info = this.GetType().GetProperty(key);
if(info == null)
return null
return info.GetValue(this, null);
}
set
{
PropertyInfo info = this.GetType().GetProperty(key);
if(info != null)
info.SetValue(this,value,null);
}
}

Check out this about indexers. The dictionary stores all the values and keys instead of using properties. This way you can add new properties at runtime without losing performance
public class User
{
Dictionary<string, string> Values = new Dictionary<string, string>();
public string this[string key]
{
get
{
return Values[key];
}
set
{
Values[key] = value;
}
}
}

You could certainly inherit DynamicObject and do it that way.
http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.trygetindex.aspx
Using the simple indexer method mentioned here by others would limit you to either returning only 'object' (and having to cast) or having only string types in your class.
Edit: As mentioned elsewhere, even with dynamic, you still need to use either reflection or some form of lookup to retrieve the value inside the TryGetIndex function.

You cannot do this until the class implements a Indexer.

If you just want to access a property based on a string value you could use reflection to do something similar:
string name = typeof(User).GetProperty("Name").GetValue(user,null).ToString();

You could build it yourself with reflection and indexer.
But for what do you need such a solution?

Related

Can I access a class variable with another variable?

i want to do a class constructor that takes a dicionary as parameter and initialize all the class variables that are listed as key in the dictionary, after of course a type conversion:
public class User
{
public int id;
public string username;
public string password;
public string email;
public int mana_fire;
public int mana_water;
public int mana_earth;
public int mana_life;
public int mana_death;
public User ()
{
}
public User(Dictionary<string,string> dataArray){
FieldInfo[] classVariablesInfoList = typeof(User).GetFields();
for(int i = 0; i < classVariablesInfoList.Length; i++)
{
if(dataArray.ContainsKey(classVariablesInfoList[i].Name)){
//missing code here :)
//need something like classVariable= dataArray["classVariablesInfolist[i].name"]; ?
}
}
}
}
but i can't find out how to do this!
Can you please help? :)
You can use the SetValue frunction from reflection:
FieldInfo f = classVariablesInfoList[i];
if (f.ReflectedType == typeof(int))
{
f.SetValue(this, Convert.ToInt32(dataArray[f.Name]));
}
else
{
f.SetValue(this, dataArray[classVariablesInfoList[i].Name]);
}
But it is a really uncommon way to do this with a dictionary. You should considder accessing the fields directly or add parameters to the constructor for any field. And fields should never be public - use properties instead.
The following will work if Convert.ChangeType() is able to handle the conversion. There are a lot of problems waiting to occur, for example handling numbers or dates where the string representation depends on the locale. I would really suggest to use usual typed constructor parameters or standard (de)serialization mechanism if possible. Or at least use a dictionary containing objects instead of strings to get rid of the conversion, again if possible.
public User(Dictionary<String, String> data)
{
var fields = typeof(User).GetFields();
foreach (field in fields)
{
if (data.ContainsKey(field.Name))
{
var value = Convert.ChangeType(data[field.Name], field.MemberType);
field.SetValue(this, value);
}
}
}
I would like to separate your problem into two parts.
1. Applying conversion
The FieldInfo type present a FieldType property that is the actual type of the field, using this Type we can use the non-generic ChangeType method of System.Convert, this method will be able convert some types to others. Luckily it support String to Int.
Usage:
Convert.ChangeType(OLD_VALUE, TARGET_TYPE);
2. Setting the field
The field info class has a SetValue method (FieldInfo.SetValue), it has two parameters, the first one is the current (ie. this) instance (or the instance you wish to change). the second is the new value you wish to set.
Putting it all together
[...]
var fieldInfo = classVariablesInfoList[i];
var name = fieldInfo.Name;
var targetType = fieldInfo.Type;
var value = Convert.ChangeType(dataArray[name], targetType);
classVariablesInfoList[i].SetValue(this, value);

Own Add Method for Dictionary<TKey,TValue> which takes Expression<Func<T>> as parameter

I'm trying to implement a Add Method for Dictionary<TKey,TValue> which takes a Propert as Parameter.
How I want to initiate the Dictionary:
ExpressionDictionary<string,string> OrigionalValues = new ExpressionDictionary<string,string>();
And I want to Add an item in a Property in code like:
public string Title
{
get { return _title; }
set
{
if (_title != value)
{
_title = value;
OrigionalValues.Add(() => Title,value);
}
}
}
My ExpressionDictionary Class:
public class ExpressionDictionary<T,TValue> : Dictionary<string, TValue>
{
public void Add(Expression<Func<T>> property, TValue value)
{
var body = property.Body as MemberExpression;
if (body != null) Add(body.Member.Name, value);
}
}
So the PropertName is stored as the TKey of the Dictionary as a string. This works when the Property is type of string, but when I try to add a DateTime property and a string Property it hangs up, because it cannot convert, which is clear.
What I'm trying to achive is that I don't need to hardcode the string Name of the Property like
OrigionalValues.Add("Title",value);
How can I design my Add Method or the ExpressionDictionary Class that I can call the Add Method from every Property type I want and the Property Name is stored as TKey? Is this even possible?
What about instantiating your dictionary like this?
var OrigionalValues = new ExpressionDictionary<object,object>();

How can I use reflection to find the properties which implement a specific interface?

Consider this example:
public interface IAnimal
{
}
public class Cat: IAnimal
{
}
public class DoStuff
{
private Object catList = new List<Cat>();
public void Go()
{
// I want to do this, but using reflection instead:
if (catList is IEnumerable<IAnimal>)
MessageBox.Show("animal list found");
// now to try and do the above using reflection...
PropertyInfo[] properties = this.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
//... what do I do here?
// if (*something*)
MessageBox.Show("animal list found");
}
}
}
Can you complete the if statement, replacing something with the correct code?
EDIT:
I noticed that I should have used a property instead of a field for this to work, so it should be:
public Object catList
{
get
{
return new List<Cat>();
}
}
You can look at the properties' PropertyType, then use IsAssignableFrom, which I assume is what you want:
PropertyInfo[] properties = this.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
if (typeof(IEnumerable<IAnimal>).IsAssignableFrom(property.PropertyType))
{
// Found a property that is an IEnumerable<IAnimal>
}
}
Of course, you need to add a property to your class if you want the above code to work ;-)
Please note that in your example, catList would not be found with GetType().GetProperties (). You would use GetType().GetFields () instead.
If you are trying to determine whether the property is defined as IEnumerable you can do this:
if (typeof(IEnumerable<IAnimal>) == property.PropertyType)
{
MessageBox.Show("animal list found");
}
If you want to know if you can assign the value of the property into a IEnumerable<IAnimal>, do this:
if (typeof(IEnumerable<IAnimal>).IsAssignableFrom (property.PropertyType))
{
MessageBox.Show("animal list found");
}
If the property type is not specific enough (like object Animal{get;set;}) to get your answer, you will need to get the value to decide. You can do this:
object value = property.GetValue(this, null);
if (value is IEnumerable<IAnimal>)
{
MessageBox.Show("animal list found");
}
Another way to do it is just call GetProperties() on the interface from within the object, opposed to on the object itself.
public static void DisplayObjectInterface(object source, Type InterfaceName)
{
// Get the interface we are interested in
var Interface = source.GetType().GetInterface(InterfaceName.Name);
if (Interface != null)
{
// Get the properties from the interface, instead of our source.
var propertyList = Interface.GetProperties();
foreach (var property in propertyList)
Debug.Log(InterfaceName.Name + " : " + property.Name + "Value " + property.GetValue(source, null));
}
else
Debug.Log("Warning: Interface does not belong to object.");
}
I like to make InterfaceName parameter a Type to avoid any typo errors when looking up GetInterface() by string name.
Usage:
DisplayObjectInterface(Obj, typeof(InterFaceNameGoesHere));
EDIT: I just noticed that your example was a collection, this will not work on a collection passed as a whole. You would have to pass each item individually. I'm tempted to delete but this will probably help others that google this same question looking for a non-collection solution.

Dynamic Dictionary usage in C#

I am using a Dynamic dictionary in C#. The problem I am facing is the behavior of TryGetMember which I am overriding in the dynamic dictionary class.
Here's the code of dynamic dictionary.
class DynamicDictionary<TValue> : DynamicObject
{
private IDictionary<string, TValue> m_dictionary;
public DynamicDictionary(IDictionary<string, TValue> a_dictionary)
{
m_dictionary = a_dictionary;
}
public override bool TryGetMember(GetMemberBinder a_binder, out object a_result)
{
bool returnValue = false;
var key = a_binder.Name;
if (m_dictionary.ContainsKey(key))
{
a_result = m_dictionary[key];
returnValue = true;
}
else
a_result = null;
return returnValue;
}
}
Here, TryGetMember will be called at runtime whenever we refer some key from outside, but it's strange that binder's Name member which always gives the key what we refer from outside, it always resolves the key name written as characters of alphabets.
e.g. if the object of DynamicDictionary made as:
Dictionary<string,List<String>> dictionaryOfStringVsListOfStrings;
//here listOfStrings some strings list already populated with strings
dictionaryOfStringVsListOfStrings.Add("Test", listOfStrings);
dynamic dynamicDictionary_01 = new
DynamicDictionary<List<String>(dictionaryOfStringVsListOfStrings);
string somekey = "Test";
//will be resolve at runtime
List<String> listOfStringsAsValue = dynamicDictionary_01.somekey
Now what happens here is "somekey" will become the value of a_binder (i.e a_binder.Name="somekey"). It should be resolved as a_binder.Name = "Test" and then from the dynamic dictionary it will locate listOfStrings against this key (i.e. actually "Test" but it resolves not the value but actual variable name as key).
Is there a way around this?
The point of dynamic typing is to make the member names themselves get resolved from the source code member access.
Dynamic typing is working exactly as it's meant to here - it's not designed to retrieve the value of the variable and use that as the member name - it's designed to use the member name you used in your source code (i.e. "somekey").
It sounds like you really don't need dynamic typing at all here - just use Dictionary<string,List<String>> as normal:
List<String> listOfStringsAsValue = dictionary[somekey];
EDIT: It sounds like you actually want to encapsulate a dictionary like this:
public class Foo // TODO: Come up with an appropriate name :)
{
private readonly Dictionary<string, List<string>> dictionary =
new Dictionary<string, List<string>>();
public List<string> this[string key]
{
get
{
List<string> list;
if (!dictionary.TryGetValue(key, out list))
{
list = new List<string>();
dictionary[key] = list;
}
return list;
}
}
}
Then you can do:
foo["first"].Add("value 1");
foo["second"].Add("value 2")
foo["first"].Add("value 1.1");
If you want to be able to attempt to fetch a list without creating a new one if it doesn't exist, you could add a method to do that.
It really doesn't sound like you need DynamicObject here.

C# Assign a variable that has a certain name

I want to slap a simple class together to pick out QueryString variables from an HTTP request that gets sent to my application. The variables are not always in the same order, but they're always there. I want to assign the variables in my class the values of the corresponding variables from the request, but I have no idea how to do this.
Code snippets:
MyHTTPRequest ar = new MyHTTPRequest("GET /submit.php?variableOne=value&variableTwo=someothervalue HTTP/1.1"); // Leaving out the rest for now
class MyHTTPRequest
{
public string variableOne;
public string variableTwo;
public string variableThree;
private string[] properties = { "variableOne", "variableTwo", "variableThree" }; // I know they're not actually properties
public MyHTTPRequest(string request)
{
string[] variablePars = request.Substring(16, request.Length - 24).Split('&'); // variablePars now contains "variableOne=value" & "variableTwo=someothervalue"
foreach (string variablePar in variablePars)
{
if (properties.Contains(variablePar.Split('=')[0])) // variableOne, variableTwo, variableThree
{
// Assign the correct variable the value
<???> = variablePar.Split('=')[1]; // I don't know how to pull this one off. variablePar.Split('=')[0] should contain the name of the variable.
}
}
}
}
Any input?
I'm sure a similar question already exists, but I did not know what to titel or tag this with.
Use the System.Web.HttpUtilityClass.ParseQueryString. It returns a NameValueCollection just like you get in ASP.NET with Request.QueryString.
// assuming you can parse your string to get your string to this format.
string queryStringText = "variableOne=value&variableTwo=someothervalue";
NameValueCollection queryString =
HttpUtility.ParseQueryString(queryStringText);
string variable1 = queryString["variableOne"];
string variable2 = queryString["variableTwo"];
Why not turn it around?
class MyHTTPRequest {
public string variableOne { get { return _values["variableOne"]; } }
public string variableTwo { get { return _values["variableTwo"]; } }
public string variableThree { get { return _values["variableThree"]; } }
NameValueCollection _values;
public MyHTTPRequest(string queryStringText) {
_values = HttpUtility.ParseQueryString(queryStringText);
}
}
You could use reflection to do this as follows:
PropertyInfo property = YourDtoClass.GetType().GetProperty("ThePropertyName");
if (property != null)
{
property.SetValue(theTargetObject, theValue);
}
Here we first get the property of the class where your properties are defined (via reflection and the property name). If a property is found with the desired name, we then set the property value on the target object.
Or using fields instead of properties:
FieldInfo field = YourDtoClass.GetType().GetField("theFieldName");
if (field != null)
{
field.SetValue(theTargetObject, theValue);
}
Update
This technique is only really safe (from a security perspective as others commented) if the target object that you are setting values on is purely a DTO, where all fields\properties are intended to be populated by query string values. This was the original viewpoint of my answer. If the target object contains fields that should not be set from query string values, then do not use this technique, as fields\properties that are not intended to be set from query string values, could be.
If your target object is a DTO, then the above is fine. I am assuming that this is the case.
http://msdn.microsoft.com/en-us/library/system.web.httprequest.querystring.aspx

Categories