Одно из моего любимого использования отражения ниже метода дампа Java. Это берет любой объект в качестве параметра и использует API Reflection Java для распечатывания каждого имени поля и значения.
import java.lang.reflect.Array;
import java.lang.reflect.Field;
public static String dump(Object o, int callCount) {
callCount++;
StringBuffer tabs = new StringBuffer();
for (int k = 0; k < callCount; k++) {
tabs.append("\t");
}
StringBuffer buffer = new StringBuffer();
Class oClass = o.getClass();
if (oClass.isArray()) {
buffer.append("\n");
buffer.append(tabs.toString());
buffer.append("[");
for (int i = 0; i < Array.getLength(o); i++) {
if (i < 0)
buffer.append(",");
Object value = Array.get(o, i);
if (value.getClass().isPrimitive() ||
value.getClass() == java.lang.Long.class ||
value.getClass() == java.lang.String.class ||
value.getClass() == java.lang.Integer.class ||
value.getClass() == java.lang.Boolean.class
) {
buffer.append(value);
} else {
buffer.append(dump(value, callCount));
}
}
buffer.append(tabs.toString());
buffer.append("]\n");
} else {
buffer.append("\n");
buffer.append(tabs.toString());
buffer.append("{\n");
while (oClass != null) {
Field[] fields = oClass.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
buffer.append(tabs.toString());
fields[i].setAccessible(true);
buffer.append(fields[i].getName());
buffer.append("=");
try {
Object value = fields[i].get(o);
if (value != null) {
if (value.getClass().isPrimitive() ||
value.getClass() == java.lang.Long.class ||
value.getClass() == java.lang.String.class ||
value.getClass() == java.lang.Integer.class ||
value.getClass() == java.lang.Boolean.class
) {
buffer.append(value);
} else {
buffer.append(dump(value, callCount));
}
}
} catch (IllegalAccessException e) {
buffer.append(e.getMessage());
}
buffer.append("\n");
}
oClass = oClass.getSuperclass();
}
buffer.append(tabs.toString());
buffer.append("}\n");
}
return buffer.toString();
}
Два пользовательских элемента управления не должны знать друг друга. Если вы хотите всегда работать с ними как с парой, подумайте о создании третьего пользовательского элемента управления для их размещения.
Должна ли форма ждать события от A, а затем начинать операцию с B?
Да, это единственный хороший способ справиться с этим.
Расширенная (бонусная?) проблема немного сложнее. Я бы справился с этим, если бы форма передавала пользовательскому элементу управления делегат методу другого пользовательского элемента управления для извлечения данных. Затем пользовательский элемент управления может вызвать метод делегата для вызова метода другого элемента управления, не зная о его реализации.
Псевдокод :
public UserControlA uca { get; set; }
...
var items = uca.Items;
Я бы сделал это вот так (я использую vb.net)
Class MyUserControlA
'Inherits UserControl '(This line will be in your desinger file)
Delegate Sub SomethingEventHandler (sender as object, e as EventArgs) '(assumes you are not going to override event args)
Public Event SomethingEvent as SomethingEventHandler
private _someData as String
Public Readonly Property MyDataGrid as DataGridView
Get
Return DataGridView1 ' this is in the designer form of the user control
End Get
Public Property SomeData as string
Get
return _someData
End Get
Set(value as string)
_someData as string
End Set
End Property
Protected Sub OnSomethingEvent()
RaiseEvent SomethingEvent(Me, EventArgs())
End Sub
'....something happens and you want to raise the event
OnSomethingEvent
End Class
Реализуйте основную форму следующим образом
Class MainForm
Implements Form 'designer file
'....other code
Sub MyUserControlA1_SomethingEvent Handles MyUserControlA1.SomethingEvent
'instead of calling a property you could override eventArgs and return the control that way.
MyUserControlB1.OtherDataGridView=MyUserControlA1.MyDataGrid
End Sub
End Class
UserControlB выглядит следующим образом:
Class UserControlB
Inherits UserControl ' designer form
'...other code
private _dataGrid as DataGridView=Nothing
Public Property DataGrid() As DataGridView
Get
Return _dataGrid
End Get
Set(ByVal value As DataGridView)
'only set if null
if _dataGrid is Nothing then _dataGrid = value
End Set
End Property
'do stuff with the control...I would always check for null
function DoSomethingWithDataGrid as integer
if _dataGrid IsNot Nothing then
return _dataGrid.Items.Count
End If
End Sub
End Class
ЭТОТ КОД НЕ ПРОВЕРЕН.
. Таким образом, это довольно слабо связано. Я думаю, что в идеальном мире вы бы обернули все, что вам нужно в UserControlA DataGrid в методах и свойствах, и использовали бы их таким образом. Но если в DataGrid много участников, на которых вы ссылаетесь, это, безусловно, проще.
Я не утверждаю, что это идеальный дизайн. Я все еще изучаю архитектуру winforms. Как вы думаете, эксперты?
Сет Б. Спирмен