Программирование на .net, обмениваемся опытом

0 голосов
спросил 06 Март, 10 от TDenis (42,620 баллов) в категории Программные продукты Esri
Предлагаю здесь обмениваться опытом людям, которые программируют в ArcGIS под .Net или просто работают с ArcObjects. Думаю, это может быть интересно не только новичкам, но и более продвинутым разработчикам.

-----------------------------------

Попробую немного затронуть тему интерфейсов. Примеры на C#, но и на VB.Net многое выглядит аналогично.

Использование методов расширения (Extension methods).
Один из основных вопросов у начинающих разработчиков под ArcGIS связан с огромным числом интерфейсов. Их действительно много и их приходится запоминать, чтобы не копаться каждый раз в справке, ища соответствующий интерфейс по названию метода или по списку интерфейсов, которые реализует рассматриваемый объект. Но это только полбеды. Допустим, вы запомнили те интерфейсы, с которыми вы работаете наиболее часто. Но это не избавляет вас от того, что вам приходится постоянно приводить эти интерфейсы один к другому (которые иногда еще и находится в различных сборках). Конечно, в рамках архитектуры системы наличие всех этих интерфейсов, группирующих методы по функционалу, может выглядеть красиво и смотреться все это будет отлично проработанным решением, но в итоге программировать становится не всегда удобно. Хочется попробовать немного упростить работу.

К примеру, когда вы работаете с геометрией, вам приходится постоянно приводить интерфейсы один к другому, например к IProximityOperator, ICurve, ITopologicalOperator, IArea.
Вместо этого можно подключить свою библиотеку с готовыми методами расширения для "основных" интерфейсов. Для полигонов (PolygonClass) - под "основным" методом я подразумеваю IPolygon, для точек (PointClass) - IPoint и т.д.
И в этом случае получается не просто библиотека, а библиотека, которой действительно удобно пользоваться.
Для того, чтобы найти, скажем, центр масс полигона, вам больше не придется делать нечто вроде:

IArea pArea = pPolygon as IArea;

return pArea.Centroid;

вместо этого можно будет написать:
return pPolygon.GetCentroid();

где GetCentroid() - это метод расширения для интерфейса IPolygon, т.е. не стандартный метод от ESRI, а наш собственный, но привязанный к IPolygon.

Кстати говоря, в данном случае всё равно далеко не всем интуитивно понятно, что IArea - это тот самый интерфейс для поиска центра.
Здесь я добавил расширяющий метод для IGeometry (для точки он вернет себя же, для линии и полигона - центр). Т.к. IPolygon наследует IGeometry, то никакого приведения не требуется.

Интерфейс IPolygon можно расширить методом GetArea(), возвращающим значение площади, этот метод мне приходится тоже использовать достаточно часто. Останется перенести туда же метод LabelPoint и тогда можно забыть про IArea насовсем.

Методы вроде StartEditing(), StopEditOperation() можно прицепить к IFeatureLayer, скрывая логику получения Workspace.
К IFeatureCursor или ICursor можно добавить метод Release(), тогда для освобождения ресурсов не потребуется вспоминать и явно обращаться к Marshal, а достаточно будет работать именно с IFeatureCursor.
К IMap можно прицепить FindLayer(), чтобы не вспоминать про метод FindMapLayer() в IGPUtilities из соответствующего пространства имен.
И т.д.

Пример метода расширения:

public static double GetDistance(this IGeometry thisGeometry, IGeometry pGeometry)

{
    return ((IProximityOperator)thisGeometry).ReturnDistance(pGeometry);
}


Ничего сложного, обычный статический метод с добавлением ключевого слова this для первого параметра, тип которого мы расширяем. И как видно из примеров, это будет не классический статический (static/shared) метод, а именно метод для экземпляров.

В выпадающем меню интеллисенса метод будет помечен специальным значком, и вы сразу сможете отличить ваш метод от стандартных. Можно давать методу комментарий на родном языке, что удобно.

Понятно, что нельзя абсолютно все пихать в "основные" интерфейсы, иначе с тем же успехом можно обходиться и вовсе без интерфейсов, а использовать класс напрямую. В этом случае получается огромный список методов и свойств, выбирать из такого списка довольно сложно (создайте экземпляр того же PolygonClass и посмотрите сколько у него разных методов). Поэтому в "основных" интерфейсах должно быть только то, что вы используете очень часто.

Конечно, в расширении есть и свои минусы. Это особенность языка C# 3.0 и официально для работы этих методов требуется framework 3.5. Хотя можно заставить их работать с более старыми версиями framework, используя вот такой хак:
http://www.c-sharpcorner.com/UploadFile/pcurnow/extmethods03242008070853AM/extmethods.aspx.

Т.е. нужно лишь добавить следующий код:
namespace System.Runtime.CompilerServices

{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]    
    public sealed class ExtensionAttribute : Attribute
    {
    }
}


Но есть и более важная проблема - расширяющие методы могут внести некоторую мешанину в "стройную" систему стандартных интерфейсов.
Перевешивают ли эти минусы в вашем случае - решайте сами.
Но использование такого подхода позволит вам реже обращаться к специализированным интерфейсам, позволит значительно быстрее писать код, который к тому же будет более простой и короткий, по которому будет легче ориентироваться, проводить рефакторинг.

Особенно это актуально, когда вам в очередной раз необходимо быстренько решить несложную, но достаточно типовую задачу - когда, например, требуется создать новую кнопку для ArcMap, которая бы находила на карте слой по его имени, проходила бы по всем записям слоя, проводила бы некоторый анализ и записывала бы куда-то результат или выводила отчет. Думаю многие писали подобное не раз. Действия часто одни и те же.

Дополнительно про расширяющие методы можно почитать тут:
http://msdn.microsoft.com/ru-ru/library/bb383977.aspx
http://msdn.microsoft.com/ru-ru/magazine/cc163317.aspx (для vb)
http://en.wikipedia.org/wiki/Extension_method

-------------------------------

Вопрос опытным разработчикам.
А что делаете вы при создании нового проекта первым делом? Создаёте и подключаете ли вы какие-нибудь собственные шорткаты, сниппеты именно для arcobjects? Пользуетесь ли вы стандартными? Пишете ли вы предварительно юнит-тесты для своего кода, непосредственно работающего с ArcObjects? С помощью mock-объектов или как?
Что делаете вы, чтобы упростить свою работу?

18 Ответы

0 голосов
ответил 21 Апр, 10 от pooperec (10,820 баллов)
Подробнее?
http://www.google.com.ua/search?sourceid=chrome&ie=UTF-8&q=pFeatureLayer.FeatureClass.CreateFeature

Первая, вторая или третья ссылка...

Отчего то вспомнилось:
Сидят в чуме мама-чукча 140см и отец-чукча 150см. Заходит сын-чукча
130см и говорит: я нашел себе невесту. Заходит девочка-чукча 120см. Мама
говорит будем играть свадьбу. Папа долго молчал, а потом говорит: а я
против, мы так до мышей до***мся.
0 голосов
ответил 07 Июль, 10 от pooperec (10,820 баллов)
TDenis
Спасибо ещё раз за Ваши топики, сейчас когда начал переходить на .НЕТ, они очень пригодились. Модераторы, закрепите пожалуйста тему в "топах"...
0 голосов
ответил 07 Июль, 10 от TDenis (42,620 баллов)
Да не, это ведь всё баловство больше) Например, методы расширения - это же своего рода "грязный хак", который нравится далеко не всем архитекторам.

-----------------
От делфи к C#, практически по стопам Андерса Хейлсберга? :)
Или какой-то другой язык выбрали?

По какой-то книжке изучаете? Или интернеты?

Если что - спрашивайте. Точно знаю, здесь ходят некоторые камрады, которые "в теме", [шаркая ножкой] ну и сам я MCP по .NET, может подскажу чего.
0 голосов
ответил 07 Июль, 10 от pooperec (10,820 баллов)
2 TDenis
Да, от Делфи к С шарп, и от СОМ к .НЕТ соответственно.

Учусь по Эндрю Троелсену (СШапр для платформы .НЕТ, как-то так называется книжка), Интернету, хелпу... Ввиду синтаксической простоты, и использования ArcObjects + ООП переход стал довольно безболезненным.

Вот недавно написал свой первый инструмент (велосипед своего рода) для простронственной выборки (полный аналог ArcMap инструмента).
0 голосов
ответил 07 Июль, 10 от TDenis (42,620 баллов)
Учусь по Эндрю Троелсену

image
0 голосов
ответил 02 Март, 11 от aviabunin (440 баллов)
arcgis Engine+C#+.NET
исходная задача - по клику на символе получить доступ к атрибутам слоя. Вроде нужно получить доступ к SelectedLayer, он есть в свойствах документа, а как получить доступ к документу? Или что почитать или где спросить? Спасибо!
0 голосов
ответил 07 Май, 12 от Chosen (200 баллов)
    Подскажи каким образом, средствами с#, при создании нового инструмента, можно выбрать любой слой на карте. Очень нужно заранее спс.
    
0 голосов
ответил 10 Май, 12 от new_sergei (2,660 баллов)
    Так точно не скажу, но навскидку - Вам надо выбрать все объекты слоя и передать это в FeatureSelection
Добро пожаловать на сайт Вопросов и Ответов, где вы можете задавать вопросы по GIS тематике и получать ответы от других членов сообщества.
...