Вопрос № 165153: Здравствуте! Помогите решить: Дан массив из десяти целых чисел (заполненный разными значениями по Вашему усмотрению). Это описания пяти сплавов из двух элементов, причем удельный вес первого элемента в полтора раза больше второго. Сплавы пронум...
Вопрос № 165201: Здравствуйте, ув. эксперты. Вопрос по механизму reflection. Сразу оговорюсь. Структура задачи не подлежит реформированию. Она должна работать именно в той конструкции,
в к. она сейчас построена. Итак. Имеется контрол на форме (по кон...
Вопрос № 165.153
Здравствуте! Помогите решить: Дан массив из десяти целых чисел (заполненный разными значениями по Вашему усмотрению). Это описания пяти сплавов из двух элементов, причем удельный вес первого элемента в полтора раза больше второго. Сплавы пронумерованы от 0 до 4. Например, если массив содержит [8,4,8,5,8,8,8,7,8,6] то нулевой сплав состоит из 8-ми частей элемента 1 и 4-х частей элемента 2. Найти номер сплава со "средним" удельным весом (есть два сплава тяжелее и два легче). В рассмотренном выше
массиве это сплав номер 4.
namespace _165153 { class Program { // Удельные веса const double mass1 = 1.5; const double mass2 = 1; static void Main(string[] args) {
// Массив по условию uint[] elements = { 8, 4, 8, 5, 8, 8, 8, 7, 8, 6 }; // Массив для расчетных удельных масс AlloyMass[] alloyMasses = new AlloyMass[elements.Length / 2]; // Считаем и сохраняем в массив for (uint i = 0; i < elements.Length - 1; i += 2) { alloyMasses[i / 2] = new AlloyMass(i / 2, CalcAlloyMass(elements[i], elements[i + 1]));
} // Сортируем полученный массив удельных масс Array.Sort(alloyMasses, (x, y) => { double diff = x.Mass - y.Mass; return diff > 0 ? 1 : diff < 0 ? -1 : 0; }); // Выводим результат Console.WriteLine("Номер сплава со средним удельным весом:{0}", alloyMasses[alloyMasses.Length / 2].No); Console.ReadKey(); }
// Метод для расчета удельной массы private static double CalcAlloyMass(uint vol1, uint vol2) { return (vol1 * mass1 + vol2 * mass2) / (vol1 + vol2); } // Класс для хранения удельной массы и номера сплава private class AlloyMass { // Конструктор public AlloyMass(uint no, double mass) { this.no = no; this.mass =
mass; } // Номер сплава private uint no; public uint No { get { return no; } } // Удельная масса private double mass; public double Mass { get { return mass; } } } } }
Результат работы:
Код:
Номер сплава со средним удельным весом:4
Ответ отправил: Micren (статус: Практикант)
Ответ отправлен: 16.04.2009, 22:19
Как сказать этому эксперту "спасибо"?
Отправить SMS
#thank 247664 на номер 1151 (Россия) | Еще номера >>
Вам помогли? Пожалуйста, поблагодарите эксперта за это!
Вопрос № 165.201
Здравствуйте, ув. эксперты. Вопрос по механизму reflection.
Сразу оговорюсь. Структура задачи не подлежит реформированию. Она должна работать именно в той конструкции, в к. она сейчас построена.
Итак. Имеется контрол на форме (по контролу был мой же вопрос №163879). Из себя он представляет текстовое поле с кнопкой в правом углу. При нажатии на кнопку открывается форма. На данный момент контрол вполне юзабельный. Но он жестко привязан к одному типу формы, к. я заранее знаю. Скажем, тип формы
MainForm. И весь обработчик клика на кнопку подвязан к этому типу. Т.е. я привожу к нему и от этого пляшу:
Код:
((MainForm)obj).<необходимые методы и/или свойства>;
Для конкртеного проекта большего и не надо. Но я хочу и
спользовать этот контрол в других своих проектах, а также делиться им с людьми. Поэтому вынес его в отдельный проект и сделал из него dll. Также для полной универсальности было добавлено свойство:
Код:
protected Form bFormValue;
public Form BindForm { get {
return bFormValue; } set { if (value.GetType().BaseType != typeof(Form)) { throw new InvalidCastException("Должна быть форма."); } if (value.GetType().GetMethod("StartValue", BindingFlags.Public | BindingFlags.Instance) == null) { throw new InvalidCastException("Форма должна иметь реализацию метода:
public void StartValue(string startValue){...}"); } bFormValue = value; } }
При попытке присвоить этому свойству значение конкретной формы (тип которой я уже НЕ знаю), во-первых, происходит проверка, а форма ли это вообще, во-вторых, эта форма должна иметь метод:
Код:
public void StartValue(string sv){}
Для чего это надо? Скорее всего, форма при открытии должна инициализироваться какими-либо стартовыми значениями. Пока что реальная необходимость передавать строку (со временем будет правильнее передавать object). И вот этот метод как раз и будет обработчиком события. Он эту строку примет и сделает с ним все, что пожелает разработчик конкретной формы. Тут, правда, мо
жно было создать конструктор с параметрами. Но это больше похоже на костыль. Плюс это не решает проблемы возможного возврата параметров. Да и вообще обмен сообщенияями между формами.
Для того, ччтобы передать строку в форму, был объявлен делегат:
Код:
public delegate void
StartValueEvent(string startValue);
и само событие:
Код:
public event StartValueEvent setStartValue;
Внимание, вопрос. Как теперь подписать форму неизвестного типа на получение этого события?
т.е. если бы тип был известен (как у меня сейчас), то это выглядело бы примерно так:
Но тут вся проблема менно в неизвестности типа формы. Т.е. задача сводится к тому,
чтобы подписать внешнюю форму на событие "от себя".
Порылся в МСДН. Нашел похожий пример (в приложении). Правда, этот пример выполняет немного другую задачу - он подписывает себя на событие от внешней формы (он делает еще нечто, но это не по теме). Немного перекроив пример получил следующий код:
Код:
//Assembly assem = Assembly.GetExecutingAssembly(); //Вот такой вариант вообще не может получить отражения формы (почему-то)
//Значит возьмем отражение формы из ядра string fullName = ""; foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies()) { if (ass.GetName().Name == "mscorlib") { fullName = ass.FullName; break; } } Assembly assem = Assembly.LoadFile(Application.ExecutablePath);
//Получим
форму Type tExForm = assem.GetType(BindForm.GetType().FullName); //Создадим ее отражение (экземпляр) Object exFormAsObj = Activator.CreateInstance(tExForm); //Возьмем "у себя" событие (к чему такие сложности мне не понятно, но по-другому не работает) EventInfo ev = this.GetType().GetEvent("setStartValue"); //и тип делегата этого события Type tDelegate = ev.EventHandlerType;
//Получим метод у формы, к. будет обрабатывать событие MethodInfo miHandler = BindForm.GetType().GetMethod("StartValue", BindingFlags.Public | BindingFlags.Instance);
//Теперь собственно, создадим полноценный делегат на обработчик Delegate d = Delegate.CreateDelegate(tDelegate, BindForm, miHandler);
//А вот проблемный код!!! //По идее, он должен подписать форму на получение событие MethodInfo addHandler = ev.GetAddMethod(); //Тут все нормально, получили "что-то",
как бы хандлер (обработчик) Object[] addHandlerArgs = { d }; //Добавили этот обработчик в список параметров //Сама подписка (чуть ниже) addHandler.Invoke(exFormAsObj, addHandlerArgs);
При попытке выполнить метод Invoke генерируется исключение:
Код:
An unhandled exception of type 'System.Reflection.TargetException' occurred in mscorlib.dll
Additional information: Объект не соответствует конечному типу.
Хотя при этом передаваемые параметры не null.
И что делать, не знаю. Нужна помощь.
Всем спасибо.
P.S. Если существует другой способ подписать форму заранее неизвестного типа на событие, то пойдет. Лишь бы это не ломало структуру задачи. P.S.S. Код подписки
происходит в классе-наследнике от UserControl (не Form!!). Возможно, это имеет значение. Хотя, вряд ли, тк.. пример из МСДН работает вообще не формой,а с обычным классом.
Отвечает: DrakoN
Здравствуйте, Грибенников Александр Сергееви! Чесно с трудом понимаю суть проблемы. Но постараюсь кратко обяснить. Если у Вас есть обект Х и есть его наследник ХХ. Знать тип ХХ вам не нужно. Можно реализовать вызов ивента для обекта Х и он будет работать для всех наследников. Помойму вы просто перемудрили.=) А) public event delegate_name SomeEvent<CustomEventArgs> где CustomEventArgs - наследник базовго EventArgs. Вот такой ивентик есть у Вас в Юзерконтроле. Теперь вы хотите форму типа Х подписать
на этот ивент. Делаем СustomControl форму. Говорим нашему контролы что он должен подписаться на это событие. А все остальные формы наследуем от этой. Б) Если есть делегат. То его можно заинвоукать. =) Для того чтобы все получилось. У контрола у делегата у ивента и внутреннего обработчика должен быть тип public.
Если этого мало. Опишите четко задачу. Попытаюсь подсказать. Так как я с трудом понимаю. Что вы хотите.
--------- От Винта!
Ответ отправил: DrakoN (статус: Практикант)
Ответ отправлен: 17.04.2009, 14:41
Как сказать этому эксперту "спасибо"?
Отправить SMS
#thank 247727 на номер 1151 (Россия) | Еще номера >>
Вам помогли? Пожалуйста, поблагодарите эксперта за это!
Скажите "спасибо" эксперту, который помог Вам!
Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
на короткий номер 1151 (Россия)
Номер ответа и конкретный текст СМС указан внизу каждого ответа.
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.