Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные работы Java и C# технологии.doc
Скачиваний:
171
Добавлен:
01.03.2016
Размер:
3.04 Mб
Скачать
      1. Позднее связывание

Традиционная постановка задачи позднего связывания может быть проиллюстрирована на следующем примере. Предположим, имеется программа, позволяющая выполнять обработку каких-либо файлов. Для обработки используются классы, реализующие интерфейс FileProcessor. Список типов обрабатываемых программой файлов и соответствующих им классов-обработчиков постоянно пополняется. Сборки, содержащие новые классы-обработчики, помещаются в отдельную папку, а программа-обработчик файлов должна уметь использовать всё новые и новые классы-обработчики без перекомпиляции.

Интерфейс класса-обработчика будет иметь единственную функцию, определяющую, может ли данный класс обработать данный файл. Поместим интерфейс в отдельную сборку. На неё будут ссылаться конкретные классы-обработчики.

Интерфейс-обработчик:

// compile with csc /t:library FileProcessor.cs

using System;

namespace FileProc

{ interface IFileProcessor

{ bool IsSupport(string filePath);

}

}

Теперь определим пару классов обработчиков. Пусть один из них будет работать с текстовыми файлами, второй – с картинками в формате ВMP. При этом каждый будет реализовывать интерфейс-обработчик, и будет помещён в отдельную сборку, ссылающуюся на сборку с интерфейсом.

Обработчик текстовых файлов:

// compile with csc /t:library TextProcessor.cs /r:FileProcessor.cs

using System;

using FileProc;

namespace TextProcessor

{ public class TextProcessor : IFileProcessor

{ override public bool IsSupport(string filePath)

{ return ".txt" == IO.Path.GetExtension(filePath).ToLower();

}

}

}

Обработчик картинок:

// compile with csc /t:library BmpProcessor.cs /r:FileProcessor.cs

using System;

using FileProc;

namespace BmpProcessor

{ public class BmpProcessor : IFileProcessor

{ override public bool IsSupport(string filePath)

{ return ".bmp" == IO.Path.GetExtension(filePath).ToLower();

}

}

}

В самом приложении, осуществляющем позднее связывание с классами-обработчиками, просто загружаются все сборки из каталога приложения. Затем запрашиваются все типы из каждой сборки, и среди типов ищутся те, что унаследованы от абстрактного класса-обработчика. После того, как нужный тип найден, создаётся его экземпляр и вызывается метод IsSupport.

// compile with csc LateBind.cs /r:FileProcessor.cs

using System;

using System.IO;

using System.Reflection;

using FileProc;

namespace LateBind

{ class Class1

{ [STAThread] //Атрибут

static void Main(string[] args)

{ if(args.Length < 1)

return;

string[] files = Directory.GetFiles(

System.Environment.CurrentDirectory, "*.dll");

foreach (string file in files)

{ Assembly assembly = Assembly.LoadFrom(file);

Type[] types = assembly.GetTypes();

foreach (Type type in types)

{ if (typeof(IFileProcessor).IsAssignableFrom(type)

&& ! type.IsAbstract

)

{ IFileProcessor processor

= (IFileProcessor)Activator.CreateInstance(type);

if (processor.IsSupport(args[0]))

{ Console.WriteLine(

"Assembly {0} can process file {1}."

, assembly.GetName().Name, args[0]);

Console.ReadLine();

return;

}

}

}

}

Console.WriteLine("Can't process file {0}.", args[0]);

Console.ReadLine();

}

}

}

Теперь, если появится необходимость обрабатывать файлы, например, формата VRML, не потребуется дорабатывать и перекомпилировать приложение. Достаточно будет разработать соответствующий класс-обработчик VRMLProcessorи поместить его в ту же папку, что и остальные классы-обработчики.