.NET на практике

Ежедневное использование .NET

Amazon AWS Service WCF Mutual Certificate authentication – fail

leave a comment »

Придется пользоваться старым вариантом, на WSE 3.0

Написано der Igel

Октябрь 24, 2009 в 9:06

Опубликовано в Development

Кодогенерация T4

с 3 комментариями

Нет, это не про Терминатора :)

Это про использование T4 Text Template Transformation Toolkit, встроенного в Visual Studio 2008 для автоматической генерации кода.

Кратко задача – есть исходники. Опять-то таки сгенерированные, но другим инструментом, Thrift.
Код на C#, публичные поля и свойства в классах с одинаковым именем, только различаются регистром.
Код необходимо использовать из VB.NET. Упс! VB.NET нечувствителен к регистру! Приплыли.

Исходники конечно есть, но они регулярно обновляются – так что их исправлять нельзя.
Классы не помечены partial – расширить напрямую тоже нельзя.

Но у нас же есть extension методы – спасибо .NET 3.5! Можно понаписать методов (эх… пока только методы, эктеншен свойств нет) с названием совпадающим со свойствами, но с каким-нибудь префиксом, подчеркиванием например.

Ок, хорошо. Но вручную писать обертки на 20 классов?! Да они еще, как я сказал, могут обновиться в будущем. Тут нужна автоматизация… И в VS 2008 она уже встроена – движок кодогенерации T4.

Файлы с расширением tt. Синтаксис очень похож на ASP.NET, только исполняются внутри Visual Studio (и не только, хостом может выступать любое приложение, и ваше в том числе).

И вот всё волшебство:

<#@ template language=«C#v3.5″ hostspecific=«true» #>
<#@ assembly name=«EDAM.dll» #>
<#@ assembly name=«System.Core» #>
<#@ import namespace=«System.CodeDom» #>
<#@ import namespace=«System.CodeDom.Compiler» #>
<#@ import namespace=«System.IO» #>
<#@ import namespace=«System.Linq» #>
<#@ import namespace=«System.Reflection» #>
<#@ import namespace=«Evernote.EDAM.Type» #>
 
// Autogenerated by <#= Host.GetType() #>
// <#= DateTime.Now #>
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING

namespace Evernote.EDAM.Type
{
<# foreach (var @class in Assembly.GetAssembly(BaseClass)
              .GetExportedTypes()
              .Where(type => !type.IsNested)
              .Where(type => type.Namespace == BaseClass.Namespace)) { #>
  public static class <#= @class.Name #>Ex
  {
  <# foreach (var prop in @class.GetProperties()) { #>
    public static <#= PrintType(prop.PropertyType) #> _<#= prop.Name #>(this <#= prop.DeclaringType #> value)
    {
      return value.<#= prop.Name #>;
    }
  <# }#>
  }
<# } #>
}
<#+ Type BaseClass = typeof(Note); #>
<#+ 
public string PrintType(Type type)
{
  var typeExpr = new CodeTypeReferenceExpression(type);
  var csProvider = Microsoft.CSharp.CSharpCodeProvider.CreateProvider(«C#»);
  var writer = new StringWriter();
  csProvider.GenerateCodeFromExpression(typeExpr, writer, new CodeGeneratorOptions());
  return writer.ToString();
} #>

 

Вкратце, по шагам:

  1. Перебираем все классы из сборки, из нужного пространства имен.
  2. Для каждого класса генерируем статический класс с таким-же именем и суффиксом Ex.
  3. Перебираем все свойства класса.
  4. Генерируем экстеншен-метод нужного типа с именем как оригинальное ствойство, но с префиксом _.
  5. Для генерация имени нужного типа используется маленькая хитрость. Так как по простому дженерики будут выводиться в IL-нотации, т.е. например System.Generic.List’1[System.String]. И это не будет компилироваться. Надо System.Generic.List<System.String> (для C#). Что и делается через CodeDom. Так как сборка на C# – то и провайдер для C# используется. Можно генерировать и в VB. Как в CodeDom, так и в самом T4 кстати.

Всё, теперь при сборке будет генерироваться набор расширений для каждого нужного класса с методами дублирующими все свойства, которые уже без проблем можно использовать в VB.NET. Кстати, в VB можно опускать скобки при вызове метода, если он не принимает параметров, что делает код еще более изящным (насколько вообще можно говорить об изящности в этой ситуации):

C# note.Attributes.Lattitude
VB.NET note._Attributes._Lattitude

 

Полезные ссылки:

Написано der Igel

Июнь 13, 2009 в 20:56

Опубликовано в Development

Отмечено как , , , , , , ,

Яндекс.Фотки API

leave a comment »

Яндекс.Фотки наконец-то открыли официальный API. Базирован на AtomPub.
Решил перевести существующие решения для Яндекс.Фоток на него (Picasa, Архив, WLW, WLPG).

Для работы с AtomPub в .NET попробовал несколько вариантов:

  1. System.ServiceModel.Syndication из .NET 3.5
    Базовые сущности ServiceDocument, AtomFeed, AtomEntry.
    Но все изменяющие операции (Insert, Update, Delete) приходится делать врукопашную, через WebRequest.
  2. Microsoft.Web.AtomPub
    Небольшая надстройка над первым пунктом из Live Framework SDK. Негибкая, на некоторых операциях с сервером от Яндекса давится.
  3. AtomSite
    Как оказалось, это серверная имплементация AtomPub, не клиент.
  4. GData .NET Client Library
    Предназначается для работы с сервисами Гугла, но есть базовая библиотека для работы с AtomPub, непривязанная к особенностям Гугла. Немного перегружена, но довольна гибкая и в исходниках!

После экспериментов остановился на последнем. Очень мне нравится конвергенция в современном мире – я объединяю двух непримиримых конкурентов.

namespace Team23.YandexFotki
{
  public class YaDataRequest : GDataRequest
  {
    ...
  }
}

Написано der Igel

Май 14, 2009 в 23:06

Опубликовано в Development

Отмечено как , , , , ,

Визуальный поиск по книгам с учетом русской морфологии.

leave a comment »

Вся информация: название, обложка, издательство, год выпуска, цены – не отрываясь от поля поиска.

Написано der Igel

Май 3, 2009 в 16:59

Опубликовано в Team23, Последние работы

Отмечено как ,

Визуальный поиск по Яндекс.Видео

leave a comment »

Визуальный поиск по Яндекс.Видео для Internet Explorer 8.

Написано der Igel

Май 2, 2009 в 21:51

Опубликовано в Team23, Последние работы

Отмечено как