C #, вызывающий экземпляр класса из строки

#c# #string #input #instance

#c# #строка #ввод #экземпляр

Вопрос:

Некоторое время я пытался найти способ вызова экземпляра класса из пользовательского ввода.

По сути, я хочу вызвать экземпляр из моего стандартного класса Vehicle, который уже был определен, однако проблема в том, что имя вызываемого экземпляра определяется выбором пользователя в поле со списком в форме.

Я предполагал, что он будет отформатирован именно так, однако при попытке вызова экземпляра я получаю сообщение об ошибке, в котором говорится, что я не могу выполнить сложное преобразование из string в StandardVehicle.

         StandardVehicle VauxhallB = new StandardVehicle();
        VauxhallB.Model = "B";
        VauxhallB.Manufacturer = "Vauxhall";
        VauxhallB.Doors = 5;
        VauxhallB.HorsePower = 200;
        VauxhallB.Transmission = "Manual";
        VauxhallB.Year = 2009;
        VauxhallB.Cylinders = 6;
        VauxhallB.Seats = 7;
        VauxhallB.Price = 17000;
        VauxhallB.Registration = "abc1243";

        StandardVehicle objname = comboBox1.Text;
  

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

Буду признателен за любую помощь.

С уважением, S.

Комментарии:

1. Это не так, как это работает. Неявное преобразование из строки в StandardVehicle не выполняется, если вы не предоставите его самостоятельно.

2. Вы не можете преобразовать строку в объект подобным образом. У вас есть список StandardVehicle экземпляров, которые вы привязываете к выпадающему списку?

Ответ №1:

Нет, это определенно не тот случай, когда нужно просто форматировать строку. Звучит так, как будто вы хотите

 Dictionary<string, StandardVehicle>
  

Заполните его, чтобы отобразить из строк в объекты, затем найдите объект, соответствующий имени, указанному пользователем.

Ответ №2:

VauxhallB это просто символ для компьютера. Пользователь не должен ссылаться на имена ваших переменных — хотя, вероятно, это возможно сделать с помощью отражения, но это сложный аспект программирования.

Лучшим способом сделать это было бы связать каждый экземпляр со строкой «name» в Dictionary<string, StandardVehicle> и выполнить поиск по ней. Что-то вроде:

 Dictionary<string, StandardVehicle> nameMap = new Dictionary<string, StandardVehicle>();
nameMap["VauxhallB"] = VauxhallB;
StandardVehicle objname = nameMap[comboBox1.Text];
  

Кроме того, это, как правило, более читаемо, если вы используете только имена в нижнем регистре для локальных переменных, чтобы лучше отличать их от классов, общедоступных методов и свойств.

Ответ №3:

Вы не можете преобразовать строку в объект, если у вас нет

  1. Конструктор, который принимает строку и создает требуемый объект
  2. Явный / неявный оператор приведения

и другой вариант

Используйте Activator.CreateInstace

третий вариант допустим, только если строка содержит допустимое имя типа, для вашего примера вы можете сделать

 Type type = Type.GetType(comboBox1.Text);
StandardVehicle objname = Activator.CreateInstace(type);
  

это сработает, если comboBox1.Text == "StandardVehicle" .

Дополнительная информация здесь:

http://msdn.microsoft.com/en-us/library/w3f99sx1.aspx

http://msdn.microsoft.com/en-us/library/wccyzw83.aspx

Ответ №4:

Попробуйте это:

 StandardVehicle selectedObject = (StandardVehicle)comboBox1.SelectedItem;
  

Конечно, ваш ComboBox должен быть привязан к коллекции StandardVehicles… Если это не так, тогда используйте Dictionary, как уже было предложено.

Ответ №5:

Сначала я тоже подумал, что вы имеете в виду отражение, но вы хотите всегда использовать свой класс StandardVehicle. Просто свойства должны быть заданы одной строкой, которую вы получаете от пользователя.

Напишите сами конструктор. Вы определяете формат отдельной строки, например, фиксированную позицию в этой строке:

 public StandardVehicle(String data)
{
    this.Model = data.Substring(0, 1);
    this.HorsePower = Int32.Parse(data.Substring(1, 4);
}
  

Не очень удобно, но может сработать. Добавьте некоторую обработку ошибок. Или загрузка XML или других форматов.

Ответ №6:

Это немного сложнее, чем ваш пример. Я собираюсь начать с быстрого и простого подхода, который, хотя и быстр и удобен, является своего рода антишаблоном, но я объясню это в конце:

 IBritishAuto car;

switch
{
    case "Vauxhall":
    {
        car = new Vauxhall(standardVehicle);    
        break;
    }
    case "Jaguar":
    {
        car = new Jaguar(standardVehicle);
    }
    ...etc.
}
  

Причина, по которой это неоптимально, заключается в том, что каждый раз, когда вы хотите добавить новый тип car, вам приходится изменять исходный блок кода и рисковать регрессией. Если вас устраивает это решение и вам все равно, вы можете прекратить чтение прямо сейчас.

Все еще существует?

Этот шаблон называется «условный диспетчер». Есть две основные стратегии для его улучшения: рефакторинг с использованием шаблона Command (который ограничен, потому что это шаблон Gang of Four) или более широкая реализация концепции, называемой «инверсия управления». Если вам интересно, вот ваши условия Google:

«рефакторинг условного диспетчера», «инверсия управления».

Удачи.