C# Reflection. Set TableAdapter ConnectionString

442 views Asked by At

I've been trying to create a new base class for a Windows Forms form. I want to have this base class go through all the tableadapters it has on it and update their connection strings without anyone adding any code to the form. They just put the tableadapters on the form and don't worry about the connection string settings as it's all handled in the base class.

The problem is my reflection code can find the property fine, but it can't set it. How can I fix it?

Below is the code:

public class cFormWS : Form
{
    public string ConnectionStringToUse { get; set; }

    public cFormWS()
    {
        Load += cFormWS_Load;
    }

    void cFormWS_Load(object sender, EventArgs e)
    {
        InitiliseTableAdapters();
    }

    private void InitiliseTableAdapters()
    {
        var ListOfComponents = EnumerateComponents();

        foreach (var ItemComp in ListOfComponents)
        {
            if (ItemComp.ToString().ToLower().EndsWith("tableadapter"))
            {
                var ItemCompProps = ItemComp.GetType().GetRuntimeProperties();

                var TASQLConnection =
                    ItemCompProps.FirstOrDefault(
                        w => w.PropertyType == typeof(System.Data.SqlClient.SqlConnection));

                if (TASQLConnection != null)
                {
                    var property = typeof(System.Data.SqlClient.SqlConnection).GetProperty("ConnectionString");

                    // How do I set the value?

                    string value = "some new connection string";

                    var ConvertedProperty = Convert.ChangeType(value, property.PropertyType);

                    // I tried seting a value. It is not working:
                    // "object does not match target type"
                    property.SetValue(TASQLConnection, ConvertedProperty, null);

                    //// I tried using a method. It is not working:
                    //// "object does not match target type"
                    //var m = property.SetMethod;
                    //ParameterInfo[] parameters = m.GetParameters();
                    //m.Invoke(m, parameters); // m.Invoke(this, parameters); // m.Invoke(ItemComp, parameters);
                }
            }
        }
    }

    private IEnumerable<Component> EnumerateComponents()
    {
        return from field in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
               where typeof(Component).IsAssignableFrom(field.FieldType)
               let component = (Component)field.GetValue(this)
               where component != null
               select component;
    }
1

There are 1 answers

5
Kenneth On BEST ANSWER

When you do SetValue, you need to pass in the object that you wish to set the property on.

  • In your first example code, you passed in ItemComp: This is incorrect, since the ConnectionString is a property of the SqlConnection which is a property of ItemComp
  • In your edited question (and my original answer) you pass in the TASqlConnection. However, this is not the object, but a PropertyInfobased of the object
  • The correct way is to get the value from the ItemComp object and pass that in:

property.SetValue(TASQLConnection.GetValue(ItemComp), ConvertedProperty, null);

ORIGINAL (INCORRECT) ANSWER:

You're trying to set a ConnectionString property of ItemComp. The ConnectionString is not a property of the TableAdapter, but of the SqlConnection (which is a property of the TableAdapter).

The correct way of setting the property would be this:

property.SetValue(TASQLConnection, ConvertedProperty, null);