Lec09
.pdfАтрибуты
using System; namespace test{
[AttributeUsage(AttributeTargets.All, Inherited = false,
AllowMultiple = true)] //Объявление атрибута. |
{ |
|
class TestAttribute : System.Attribute |
||
private string name; |
//Поле атрибута. |
|
public TestAttribute(string name){//Конструктор атрибута. |
||
this.name = name; |
|
|
} |
|
|
public virtual string Name{//Свойство только для чтения. |
||
get{ |
|
|
return name; |
|
|
} |
|
|
} |
|
|
} |
|
|
//Конец объявления атрибута. |
|
|
[TestAttribute("NAME")] |
//Применение атрибута к классу. |
|
class Test{ |
|
|
static void Main(){ |
|
|
GetAttribute(typeof(Test));
}
public static void GetAttribute(Type t){ TestAttribute att =
(TestAttribute)Attribute.GetCustomAttribute(t, typeof(TestAttribute));
Console.WriteLine("{0}", att.Name);
}}}
Результат:
NAME
21
Сериализация
Для того, чтобы класс стал сериализуемым, достаточно объявить его с атрибутом Serializable.
namespace Serial
{
[Serializable()] class Worker
{
public int age; public int id;
}
}
После этого экземпляр класса можно, например, целиком сохранять в файл и читать из файла (именно экземпляр класса целиком, а не поля класса по отдельности).
22
Сериализация
using System; using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary; namespace Serial{
class Program{
static void Main(string[] args){
//Задаем экземпляр класса. Worker w = new Worker(); w.age = 22;
w.id = 2;
//Сериализуем класс.
FileStream fs = new FileStream("1.txt", FileMode.Create, FileAccess.Write);
IFormatter bf = new BinaryFormatter(); bf.Serialize(fs, w);
fs.Close();
// Десериализуем класс.
fs = new FileStream("1.txt", FileMode.Open, FileAccess.Read);
Worker w1 = (Worker)bf.Deserialize(fs); Console.WriteLine("age: " + w1.age + ", id: " + w1.id); fs.Close();
}}}
Результат: age: 22, yoe: 2
23
Nullable типы
Как известно,value-типы(к ним относятся,например, int, byte и другие)не могутприниматьзначениеnull.
Но иногдатакаяпотребностьвозникает.Например, при работе с базамиданных - в столбцетаблицымогутхранитсязначения целоготипа и, кроме того,могутдопускатьсянеопределенные значения(NULL).
Nullable-типы могут принимать,кроме собственнозначений соотвествующеготипа,значениеnull.
Пример:
Nullable n; n = null;
Упрощенныйсинтаксис:
int? n;
С точки зрения реализации все nullable-типы являются экземплярами структуры System.Nullable.
24
Рефлексия
Иногда нам требуется динамически создать некий код. Созданная динамически сборка может существовать только в памяти или же может быть сохраненной на диск в виде файла.
Сначала мы должны сгенерировать сборку, затем на основании этой сборки - модуль, потом на основании этого модуля - тип (например, класс), потом на основании этого типа (класса) - его члены (конструкторы, методы и т. п.). И, уже в самом конце, мы создаем непосредственно сгенерированный на предыдущих шагах тип.
25
Рефлексия
// Создание имени сборки.
AssemblyName an = new AssemblyName("MyAssembly"); an.Version = new Version("1.0.0.0");
//Создание сборки. AssemblyBuilder ab;
ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save);
//Создание модуля в сборке.
ModuleBuilder mb = ab.DefineDynamicModule("MyModule", "My.dll"); // Создание типа в сборке.
TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public); // Создание конструктора без параметров.
ConstructorBuilder cb0 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
//Добавление кода для конструктора. ILGenerator il0 = cb0.GetILGenerator(); il0.Emit(OpCodes.Ret);
//Создание конструктора с параметром типа string.
ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(string)});
//Добавление кода для конструктора. ILGenerator il = cb.GetILGenerator(); il.EmitWriteLine("Constructor"); il.Emit(OpCodes.Ret);
//Непосредственное создание типа. tb.CreateType();
//Сохранение типа в файл.
ab.Save("qqq.dll");
26
Применение пространства имен
Если вы подключили в проекте два пространстваимен, например ns1 и ns2,
using ns1; using ns2;
которыевключают в себя класс Class1, то при попытке создатьэкземпляр данного класса возникнет ошибка
Class1 c = new Class1();
Компилятор не знает, откуда создаватькласс:
из пространства имен ns1 или ns2. В таком случае надо конкретно указыватьпространство имен
ns1.Class1 c = new ns1.Class1();
27