Создание обобщённых методов, интерфейсов, классов

Мы можем создавать собственные обобщенные методы,

структуры, классы, интерфейсы. Ключевое слово 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!");

}

}

}