С# отражение. Установить строку подключения адаптера таблицы

Я надеюсь, что кто-то может помочь с этим. Я пытался создать новый базовый класс для WinForm. Что я хочу сделать, так это заставить этот базовый класс пройти через все имеющиеся у него адаптеры таблиц и обновить их строки подключения без добавления какого-либо кода в форму. Они просто помещают адаптеры таблиц в форму и не беспокоятся о настройках строки подключения, поскольку все это обрабатывается в базовом классе.

Проблема, с которой я сталкиваюсь, заключается в том, что мой код отражения может найти свойство в порядке, но не может его установить. Кто-нибудь может помочь?

Ниже приведен код (обновлено)

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);

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


                    //// tried using a method.  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;
    }  

person Dirk Diggler    schedule 25.06.2015    source источник
comment
Здесь вам не нужно отражение (или ваш код не имеет никакого смысла для его предполагаемого использования).   -  person leppie    schedule 25.06.2015
comment
Насколько мне известно, нет другого способа сделать то, что я хочу, в автоматическом режиме.   -  person Dirk Diggler    schedule 25.06.2015
comment
Это было бы верно только в том случае, если адаптеры таблиц не имеют общего базового класса. Имеет ли это? MSDN довольно расплывчато относится к этому.   -  person leppie    schedule 25.06.2015
comment
И даже в этом случае вы все равно можете избежать отражения, применив известный интерфейс к сгенерированному классу и приведя к нему ItemComp.   -  person leppie    schedule 25.06.2015
comment
TableAdapter наследуется от Component. Применение интерфейса к сгенерированному классу будет означать, что при повторном создании он потеряет интерфейс, нет?   -  person Dirk Diggler    schedule 25.06.2015
comment
Нет, должен быть создан файл для пользовательского кода при первом его создании.   -  person leppie    schedule 25.06.2015
comment
Я посмотрел, что на самом деле могу переопределить базовый класс каждого адаптера таблицы, чтобы использовать другой класс и делать что-то по-другому. НО это долго, поскольку это широкий. Это не решает проблему. Если мне нужно обновить все мои адаптеры таблиц, я также могу написать код, когда буду их использовать. Мне нужно автоматизированное неинвазивное решение, которое мой код отражения должен/исправил бы, если бы я мог заставить заданное значение работать правильно.   -  person Dirk Diggler    schedule 25.06.2015


Ответы (1)


РЕДАКТИРОВАТЬ:

Когда вы делаете SetValue, вам нужно передать объект, для которого вы хотите установить свойство.

  • В вашем первом примере кода вы передали ItemComp: это неверно, поскольку ConnectionString является свойством SqlConnection, которое является свойством ItemComp
  • В вашем отредактированном вопросе (и моем первоначальном ответе) вы передаете TASqlConnection. Однако это не объект, а PropertyInfoоснованный на объекте
  • Правильный способ - получить значение из объекта ItemComp и передать его:

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

ИСХОДНЫЙ (НЕПРАВИЛЬНЫЙ) ОТВЕТ:

Вы пытаетесь установить свойство ConnectionString для ItemComp. ConnectionString является свойством не TableAdapter, а SqlConnection (который является свойством TableAdapter).

Правильный способ установки свойства будет следующим:

property.SetValue(TASQLConnection, ConvertedProperty, null);
person Kenneth    schedule 25.06.2015
comment
Неа. То же сообщение об ошибке. Я уже пробовал много разных комбинаций. - person Dirk Diggler; 25.06.2015
comment
Да, проблема в том, что вы передаете объект PropertyInfo, а не фактический объект. Смотрите мой отредактированный ответ для объяснения и исправления - person Kenneth; 25.06.2015
comment
Спасибо за ответ. Это все еще не работает. У меня сейчас другая ошибка. Исключение было вызвано целью вызова. - person Dirk Diggler; 25.06.2015
comment
Посмотрите на внутреннее исключение. Если вы используете свой пример кода, строка подключения имеет неправильный формат, и фактическое назначение не будет выполнено. - person Kenneth; 25.06.2015
comment
Да, ты прав. Я не думал, что это должна быть действительная строка подключения, поскольку в этот момент она не подключена, но похоже, что набор проверяет ее. - person Dirk Diggler; 25.06.2015