Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reflection, access members of "this".

Status
Not open for further replies.

tgreer

Programmer
Oct 4, 2002
1,781
US
I thought I could use Reflection to dynamically set properties within a class library. I know this is a bit strange, you'll have to trust I have a reason for this :)

Say I have two strings:

Code:
private string _field1;
private string _field2;

Within that same class, I want a method that would take two strings:

Code:
public void setValue(string K, string V)
{
  // using Reflection, set variable "K" equal to value "V"
}

An external program using this class library could:

Code:
MyClass x = new MyClass();

x.setValue("_field1","Hello world!");

Yes, I know I could create a public property that would get/set the private "_field1", and then I could simply access it directly. My actual need is more complex, and this is the simplest example I could think of that would still have the core requirement I seek, namely:

How can a class, get/set the value of a string object using a string VALUE equal to the name of the corresponding string object?

How can I make _field1 = "Hello world!", using "x" when "x" = "_field1"?

The actual problem:

I'm writing a class that will read/write/parse a particular fixed-width record format. The record contains a massive number of fields. Each field has a specific size.

Users of the class library will be able to set the value of all relevant fields and write the record(s).

If you've worked with fixed-width files before, you know that all fields, including empty fields, must be padded-out with spaces.

Each field will be a property (private/public strings) in the class. What I'm seeking is a more efficient way of initializing all the strings/fields to be fully padded out with spaces according to the size they need to be.

My thought was to create a Dictionary with each field/string name as a key and the field size as an integer value.

In the class constructor, I could do a foreach loop, getting the name of the string and it's size, and use "PadRight()" to fill that string with spaces.

The problem is, the "name of the string" doesn't equal the actual string. So I'd hoped that Reflection would allow me to say:

"Go get the string object named "whatever" and fill it with spaces".

Sorry for the verbosity; thanks for reading this far.

Thomas D. Greer
 
Here's my solution. I'd like commments on this approach. Am I dramatically overcomplicating the issue? The goal again is for the class constructor to initiliaze certain public properties, filling them a certain amount of spaces.

The names of the properties, as well as the required "size" and/or length, are contained in a Dictionary.

If there is a more efficient and clear (self-documenting) way of doing this, I'd like to hear about it.

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace TGREER
{
    public class GenericIO
    {
        // first all private/public fields
        
        private string _field1 = "";
        public string Field1
        {
            get { return _field1; }
            set { _field1 = value; }
        }
        private string _field2 = "";
        public string Field2
        {
            get { return _field2; }
            set { _field2 = value; }
        }
        private string _field3 = "";
        public string Field3
        {
            get { return _field3; }
            set { _field3 = value; }
        }

        StringBuilder workString = new StringBuilder();
        private Dictionary<string, int> _fieldLengths = new Dictionary<string, int>(3);

        public GenericIO()
        {
            // class constructor
            _fieldLengths.Add("Field1", 20);
            _fieldLengths.Add("Field2", 5);
            _fieldLengths.Add("Field3", 10);

            // use Reflection to use the strings in the Dictionary to retrieve the actual string object
            Type MyType = this.GetType();

            workString.Append(" ");

            foreach (KeyValuePair<string, int> kvp in _fieldLengths)
            {
                workString.Remove(0, workString.Length);
                workString.Insert(0, " ", kvp.Value);
                PropertyInfo Mypropertyinfo = MyType.GetProperty(kvp.Key.ToString());
                Mypropertyinfo.SetValue(this, workString.ToString(), null);
            }
        }
    }
}

I know it would be more efficient simple to define the private variables as space-filled strings:

private _field1 = " ";

The problem is maintainability. What if a slip of the fingers causes one of those spaces to be deleted?

Next step is to rewrite the Public "getter" procedures to maintain the trailing spaces and to generate an error if the value is too long.

Thomas D. Greer
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top