Soft Reference to object properties

K

kbin

Hi all,

I'm wondering if it is possible to have some sort of soft reference to
an object's properties by using a string representing the property
name. Let me explain by an example, here is my class:

public class thing {
public string model {
get; set;
}
public string make {
get; set;
}
}

And then I want to do something like the following:

thing k = new thing();
string propname = "model";
k[propname] = "Model name KS445";
k["make"] = "Maker Ltd.";

In JavaScript this is possible by using the above syntax, and in perl,
most objects are Hashes where all properties are available using the
$object->{'propname'} syntax, but is there some sort of mechanism in
csharp to do the same thing?

--Kalle
 
A

Alberto Poblacion

kbin said:
I'm wondering if it is possible to have some sort of soft reference to
an object's properties by using a string representing the property
name. Let me explain by an example, here is my class:

public class thing {
public string model {
get; set;
}
public string make {
get; set;
}
}

And then I want to do something like the following:

thing k = new thing();
string propname = "model";
k[propname] = "Model name KS445";
k["make"] = "Maker Ltd.";

In JavaScript this is possible by using the above syntax, and in perl,
most objects are Hashes where all properties are available using the
$object->{'propname'} syntax, but is there some sort of mechanism in
csharp to do the same thing?

It is called "Reflection":

using System.Reflection;
....
thing k = new thing();
Type t = typeof(thing);
PropertyInfo pi = t.getProperty("model");
pi.SetValue(k, "Model name KS445");
t.getProperty("make").SetValue(k, "Maker Ltd.");
 
M

Marc Gravell

Note that PropertyInfo supports indexed properties, so you need an
extra null there:

pi.SetValue(k, "Model name KS445",null);
t.GetProperty("make").SetValue(k, "Maker Ltd.",null);

Actually, I'd probably suggest TypeDescriptor instead; simpler and
more flexible (and less code smell):

PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(k);
string oldModel = (string) props["model"].GetValue(k);
props["model"].SetValue(k, "new model");
props["make"].SetValue(k, "new make");

Marc
 
S

Stanimir Stoyanov

As Alberto pointed out, it is possible using Reflection. If your application
is compiled against .NET 3.0 or newer you might find the following code I
wrote for another project of mine useful. It made my config file load
implementation a lot easier using a generic extension method:

static class Extensions
{
public static T SetProperty<T>(this T o, string property, object
value)
{
Type t = o.GetType();
ValueType vt = null;

if (o is ValueType)
{
vt = (ValueType)(object)o;
t = vt.GetType();
}

PropertyInfo pi = t.GetProperty(property);

if (pi == null)
throw new InvalidOperationException(string.Format("Property
{0} does not belong to type {1}", property, t.FullName));

if (pi.CanWrite)
if (vt != null)
pi.SetValue(vt, value, null);
else
pi.SetValue(o, value, null);
else
throw new InvalidOperationException(string.Format("Property
{0} of type {1} is read-only", property, t.FullName));

if (vt != null)
o = (T)(object)vt;

return o;
}
}

Usage:
TimeZoneNotFoundException t = new TimeZoneNotFoundException();

t.HelpLink = "initial value";
t.SetProperty("HelpLink", "new value");

// t.HelpLink is "new value"

Note: if you use the extension method against a value type (a structure such
as Point or Size) you have to use the following syntax because of boxing:

Point p = new Point(100, 200);

p = p.SetProperty("X", 10);
p = p.SetProperty("Y", 24);

// Notice that we had to assign the new value to p. Every Point
instance is a value type and not a reference one
 
J

Joern Schou-Rode

It is called "Reflection":

.... and it cannot really be compared to what you can do in dynamically
typed languages like JavaScript and Perl. Reflection in C# is indeed a
neat and useful feature, but it comes at a price: you avoid compile time
type check, and in many cases you will pay a noticable performance penalty.

So when should one use reflection? Well, if you need some kind of config
scheme where an external config file tells what classes to instansiate or
which namespaces to search in, reflection is probably the way to go. In
most other cases where reflection comes up as an option, it might be wiser
to rethink the problem, and try to find a design that allows the problem
to be solved whilst keeping the static system intact. Maybe someone has
fought with a similar problem before and cooked up a design pattern for it:

http://en.wikipedia.org/wiki/Software_design_pattern
 
M

Marc Gravell

Of course, C# 4.0 promises much more with "dynamic". We all wait
breath held ;-p
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top