tags:

views:

119

answers:

3

I'm having a bit of trouble with a C# program I'm writing and it'd be great if someone could help.

The background is this, not terribly important, but it's why I need to figure out how to do it:

I'm using a database's Web Services to retrieve information about an entry in the database. Each access to the database returns an Object with many many properties. Using the ID of the database entry, you tell it what information you want filled in about the object it returns by filling an array of which properties to be retrieved. Any property not in the array is left as it's default value (usually null)

The Problem: I want the user to be able to select a property of an Object (not get the value, just select which property) as below:

projectFields[0] = Primavera.Ws.P6.Project.ProjectFieldType.(project_properties.Text);

Where project_properties.Text is a string of the name of the Property I want to set projectFields[0] to.

Can anyone help? Thanks in Advance :)

Edit: Thanks for the answer guys. While they do let me get the value out of Objects Dynamically, that isn't quite what I was looking for... I'm not looking to retrieve a value, I'm only looking to set which Property projectFields[0] is equal too. for example, suppose the user selects Id as the information they want returned about the project. To do that, I'd set:

projectFields[0]=Primavera.Ws.P6.Project.ProjectFieldType.Id;

then I'd make a call to the Database, and I'd get the project Object back, with Id having been filled out for the project while all other properties would be left to their defaults. Basically, if I were to do it the way these examples suggest, I'd have to retrieve every property in the Object first, then access the member the user is interested in which would be slow/inefficent if I can make the way I'm trying to do it work.

I know it's strange how the database is accessed, but I'm using web Services so I don't have the option to change anything about the calls to the database.

+2  A: 

C# is a statically typed language. The compiler wants to know you property you mean at compile time.

However, you can do this with reflection if you want to. Alternatively, if you know the type of the data in advance, you could use a switch statement. (Example of both approaches coming.)

using System;
using System.Reflection;

public class Demo
{
    public string Foo { get; set; }
    public string Bar { get; set; }
    public string Baz { get; set; }
}

public class Test
{
    static void Main()
    {
        Demo demo = new Demo { 
            Foo = "foo value", 
            Bar = "bar value", 
            Baz = "surprise!"
        };
        ShowProperty(demo, "Foo");
        ShowProperty(demo, "Bar");
        ShowProperty(demo, "Baz");
        ShowDemoProperty(demo, "Foo");
        ShowDemoProperty(demo, "Bar");
        ShowDemoProperty(demo, "Baz");
    }

    // Here we don't know the type involved, so we have to use reflection
    static void ShowProperty(object x, string propName)
    {
        PropertyInfo property = x.GetType().GetProperty(propName);
        if (property == null)
        {
            Console.WriteLine("No such property: {0}", propName);
        }
        else
        {
            Console.WriteLine("{0}: {1}", propName,
                                          property.GetValue(x, null));
        }
    }

    // Here we *know* it's a Demo
    static void ShowDemoProperty(Demo demo, string propName)
    {
        string value;

        // Note that this is very refactoring-unfriendly. Generally icky!
        switch (propName)
        {
            case "Foo": value = demo.Foo; break;
            case "Bar": value = demo.Bar; break;
            case "Baz": value = demo.Baz; break;
            default:
                Console.WriteLine("No such property: {0}", propName);
                return;
        }
        Console.WriteLine("{0}: {1}", propName, value);

    }
}

I agree with the other answers which suggest this probably shows a slightly scary design...

Jon Skeet
+3  A: 

You can probably achieve what you want through Reflection (example), but I get a distinct feeling that there may be an issue with the design of your system.

Fredrik Mörk
A: 

You can use reflection - See property info class.

Dario