Создание обобщённых методов, интерфейсов, классов
Мы можем создавать собственные обобщенные методы,
структуры, классы, интерфейсы. Ключевое слово where,
стоящее после описания обобщенного метода
(класса, интерфейса), задает ограничение на параметр
типа Т. Т может быть только значимым типом, или
иметь в качестве базового какой-то определенный класс.
Пример:
// Этот метод осуществляет обмен значений двух
//значимых типов
public static void Swap<T>(ref T a, ref T b)
where T : struct
{
Console.WriteLine("You sent the Swap()
method a {0}", typeof(T));
T temp;
temp = a;
a = b;
b = temp;
}
Ниже приведен пример обобщенной структуры.
public struct Point<T>
{
// обобщенные поля данных
private T xPos;
private T yPos;
// конструктор
public Point(T xVal, T yVal)
{
xPos = xVal;
yPos = yVal;
}
// Обобщенные свойства
public T X
{
get { return xPos; }
set { xPos = value; }
}
public T Y
{
get { return yPos; }
set { yPos = value; }
}
public override string ToString()
{
return string.Format("[{0}, {1}]", xPos, yPos);
}
}
Наконец рассмотрим пример обобщенного интерфейса и
класса, который этот интерфейс реализует.
public interface IBinaryOperations<T>
{
T Add(T arg1, T arg2);
T Subtract(T arg1, T arg2);
T Multiply(T arg1, T arg2);
T Divide(T arg1, T arg2);
}
public class BasicMath : IBinaryOperations<int>
{
public BasicMath() {}
// IBinaryOperations<int> Members
public int Add(int arg1, int arg2)
{ return arg1 + arg2; }
public int Subtract(int arg1, int arg2)
{ return arg1 - arg2; }
public int Multiply(int arg1, int arg2)
{ return arg1 * arg2; }
public int Divide(int arg1, int arg2)
{ return arg1 / arg2; }
}
БИЛЕТ 18
Отражение типов - процесс нахождения типов во время выполнения.
Классы в пространстве имен System.Reflection вместе с System.Type позволяют получать сведения о загруженных сборках и определенных в них типах, таких как классы, интерфейсы и типы значений. Отражение можно также использовать для создания экземпляров типов во время выполнения, для вызова этих экземпляров и получения доступа к ним.
Класс System.Type определяет несколько членов, которые можно задействовать для исследования метаданных типов. Многие из этих членов возвращают типы из пространства имен System.Reflection. Пример: IsAbstract, IsArray, IsClass, IsEnum, IsValueType (Эти свойства позволяют получать различную основную информацию о типе: является ли он массивом, абстрактным, значимым и т.д.), GetConstructors(), GetEvents(), GetFields(), GetInterfaces(), GetMethods(), GetProperties(), GetNestedTypes() (Эти методы позволяют получить массив, содержащий требуемые элементы(интерфейсы, методы, свойства и т.д.). Каждый метод возвращает соответствующий массив (например, GetFields() возвращает массив FieldInfo, GetMethods() возвращает массив MethodInfo). Каждый из этих методов имеет форму в единственном числе, например GetMethod().),GetType() (Статический метод возвращает экземпляр класса Type на основании переданного имени), InvokeMember() (Метод позволяет выполнять позднее связывание для заданного элемента)
Позднее связывание - техника, позволяющая создать экземпляр некоторого типа и вызывать его члены во время выполнения, не имея информации о нем во время компиляции.
Динамическая загрузка - некоторый механизм, позволяющий указать, какой модуль встроить. Расширяемое приложение должно определить поддерживает ли модуль нужную функциональность, здесь требуется отражение. И наконец, расширяемое приложение должно получить ссылку на необходимый класс или интерфейс и вызвать его члены. Для этих действий и необходимо позднее связывание.
Приведем пример расширяемого приложения. Сначала определим общий интерфейс, который будет реализован каждым встраиваемым модулем.
public interface IAppFunctionality
{
void DoIt();
}
Код встраиваемого модуля может быть таким:
public class TheCSharpModule : IAppFunctionality
{
void IAppFunctionality.DoIt()
{
MessageBox.Show("You have just used the C# snap in!");
}
}
Теперь приведем код формы расширяемого приложения Windows Forms.
partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool LoadExternalModule(string path)
{
bool foundSnapIn = false;
IAppFunctionality itfAppFx;
// Динамическая загрузка выбранного модуля.
Assembly theSnapInAsm = Assembly.LoadFrom(path);
// Получение всех типов сборки
Type[] theTypes = theSnapInAsm.GetTypes();
// Поиск типа, реализующего интерфейс IAppFunctionality.
for (int i = 0; i < theTypes.Length; i++)
{
Type t = theTypes[i].GetInterface("IAppFunctionality");
if (t != null)
{
foundSnapIn = true;
// Позднее связывание для создания экземпляра типа
object o = theSnapInAsm.CreateInstance(theTypes[i].FullName);
// Вызов метода DoIt() интерфейса
itfAppFx = o as IAppFunctionality;
itfAppFx.DoIt();
lstLoadedSnapIns.Items.Add(theTypes[i].FullName);
}
}
return foundSnapIn;
}
// Обработчик события выбора пункта меню «загрузка модуля»
private void snapInModuleToolStripMenuItem_Click_1(object sender, EventArgs e)
{
// Открытие диалога для выбора модуля для загрузки
OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == DialogResult.OK)
{
if (LoadExternalModule(dlg.FileName) == false)
MessageBox.Show("Nothing implements IAppFunctionality!");
}
}
}