SharePoint 2010 Beta доступен для закачки TechNet и MSDN подписчикам

Дождались, наконец-то SharePoint Server 2010 Beta доступен для скачивания
подписчикам TechNet и MSDN.
https://msdn.microsoft.com/en-us/subscriptions/securedownloads/default.aspx

Напоминаю вам, что доступен он только в x64 редакциях, а так же есть Русская
редакция.

Так же выложенны все продукты линейки Office 2010.

Можно также посмотреть выступления с конференции «Платфторма 2010″, посвященные SharePoint 2010:

  1. Microsoft SharePoint Server 2010: первое знакомство
    http://www.techdays.ru/videos/1522.html
  2. Архитектура идеального предприятия, внедрившего у себя все компоненты Microsoft Office System
    http://www.techdays.ru/videos/1524.html

SharePoint

Ноябрь 16, 2009. Метки: , , . Uncategorized. Оставить комментарий.

Как подружить ASP.NET Controls и DI-контейнер

Интро

В последнее время решил немного освежить свои знания в ASP.NET, в связи с чем углубился в процессы генерации кода контролов по разметке (*.ascx, *.aspx) и обнаружил что можно делать очень интересные решения, о которых  о хочу поведать. Итак сегодня мы узнаем, как подружить наш Dependency Injection контейнер с генерируемым контролами кодом.

Поехали

DependencyInjection_Solution[1]

В качестве DI-контейнера будет выступать Microsoft Unity, но это не принципиально, всё что будет касаться DI не зависит от используемого контейнера.

Проблема состоит в следующем – есть некоторый ASP.NET Control, в который мы хотим внедрит зависимости, а так же воспользоваться услугами Service Locator’а для управления интересующими нас зависимостями.

В Microsoft Unity есть некоторые средства для того, чтобы сделать это не прилагая особенных усилий: мы можем произвести инъекцию в свойство элемента управления, нас интересующее примерно следующим образом:

  1. Отметить атрибутом Dependency необходимое свойство
    public class MyControl : UserControl
    {
            [Dependency]
            public MyPresenter Presenter
            {
                get { return _presenter; }
                set
                {
                    _presenter = value;
                    _presenter.View = this;
                }
            }
    }
  2. Проинициализировать элемент управления можно следующим образом

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        _сontainer.BuildUp(GetType(), this);
    } 
  3. Позаботиться о местоположении контейнера в вашем приложении, я предлагаю использовать для этого HttpApplication, унаследовавшись от которого и произведя небольшие модификации файла global.asax мы получаем необходимое нам хранилище для контейнера, обращаться с ним необходимо примерно следующим образом

    ((Sapphire.Application)HttpContext.Current.ApplicationInstance).Container

Решение вполне пригодное, однако пуристические воззрения не дают оставить решение на данной стадии, и думаю, что просто необходимо заменить инъекцию свойства на инъекцию в конструктор, тем более подобный подход – это далеко не то, что мы можем выжать из Unity.

Т.е. наш интерес состоит в том, чтобы класс MyUserControl выглядел примерно так (думаю сборщику страницы это не совсем понравится)

public class MyControl : UserControl
{
    public MyControl(MyPresenter presenter)
    {
         _presenter = presenter;
         _presenter.View = this;
    }
}

Предлагаю этим и заняться. Начнём с того, что у элементов управления, описанных в разметке страницы, при генерации страницы указываются их конструкторы без параметров, интересно, как можно управлять данным процессом, первоначально, покопавшись в web.config я предполагал сделать это через:

<buildProviders>
    <add extension=«.aspx» type=«System.Web.Compilation.PageBuildProvider»/>
    <add extension=«.ascx» type=«System.Web.Compilation.UserControlBuildProvider»/>
    …
</buildProviders>

Однако реализация своего PageBuildProvider’а – довольно серьезное занятие, думаю отложить это для серьезной на то необходимости. Однако благодаря BuildProvider’ам можно генерить к примеру слой доступа к данным, для этого надо:

Написать и зарегестрировать обработчик для какого-нибудь своего расширения, к примеру *.dal и сделать что-нибудь наподобее http://www.codeproject.com/KB/aspnet/DALComp.aspx

кстати подобная логика реализована в SubSonic http://dotnetslackers.com/articles/aspnet/IntroductionToSubSonic.aspx

так же интересная реализация наследования страницы от generic типов http://stackoverflow.com/questions/1480373/generic-inhertied-viewpage-and-new-property

ещё можно, к примеру генерировать исключения, объекты передачи данных и многое другое, ограничением является лишь ваша фантазия.

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

[ControlBuilder(typeof(MyControlBuilder))]
public class UserControl : System.Web.UI.UserControl
{
}

Теперь разберемся с реализацией  MyControlBuilder, этот тип должен наследовать от ControlBuilder и с помощью перегрузки ProcessGeneratedCode мы с вами сможем указать сборщику на необходимость использования нашего кода вместо вызова конструктора без атрибутов элемента управления:

    public override void ProcessGeneratedCode(CodeCompileUnit codeCompileUnit,
                                              CodeTypeDeclaration baseType,
                                              CodeTypeDeclaration derivedType,
                                              CodeMemberMethod buildMethod,
                                              CodeMemberMethod dataBindingMethod)
    {
      codeCompileUnit.Namespaces[0].Imports.Add(new CodeNamespaceImport(«Sapphire.Web.UI»));
      ReplaceConstructorWithContainerResolveMethod(buildMethod);
      base.ProcessGeneratedCode(codeCompileUnit, baseType, derivedType, buildMethod, dataBindingMethod);
    }

самое интересно скрывает метод ReplaceConstructorWithContainerResolveMethod

    private void ReplaceConstructorWithContainerResolveMethod(CodeMemberMethod buildMethod)
    {
      foreach (CodeStatement statement in buildMethod.Statements)
      {
        var assign = statement as CodeAssignStatement;

        if (null != assign)
        {
          var constructor = assign.Right as CodeObjectCreateExpression;

          if (null != constructor)
          {
            assign.Right =
              new CodeSnippetExpression(
                string.Format(«SapphireControlBuilder.Build<{0}>()»,
                              ControlType.FullName));
            break;
          }
        }
      }
    }

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

Однако это ещё не решении задания, т.к. есть метод динамической загрузки элемента управления Page.LoadControl(), для него придётся написать свой вариант

  public static class PageExtensions
  {
    public static UserControl LoadAndBuildUpControl(this Page page, string virtualPath)
    {
      var control = page.LoadControl(virtualPath);
      return SapphireControlBuilder.Build<UserControl>(control.GetType());
    }
  }

Вот мы и справились с поставленной задачей, однако это ещё не всё. А почему теперь не воспользоваться всеми преимуществами Unity, и не внедрить в наш элемент управления AOP времени исполнения с помощью Unity Interception.

К примеру мы можем сделать следующее

public class MyControl : UserControl
{
    [HandleException]
    public override void DataBind()
    {
      base.DataBind();
    }
}

Это будет означать, что обработка исключений должна добавляться на лету, к тому ж предоставляя нам возможность её изменения во время исполнения, для начала пусть её реализация будет примерно следующая

  [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
  public class HandleExceptionAttribute : HandlerAttribute
  {
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
      return new ExceptionHandler();
    }
  }

  public class ExceptionHandler : ICallHandler
  {
    /// <exception cref=»SapphireUserFriendlyException»><c>SapphireUserFriendlyException</c>.</exception>
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
      var result = getNext()(input, getNext);
      if (result.Exception == null)
        return result;
      throw new SapphireUserFriendlyException();
    }

    public int Order { getset}
  }

Ну и конечно же надо сконфигурировать контейнер для создания наших прокси-обработчиков

    public static T Build<T>()
    {
      return (T)((Application)HttpContext.Current.ApplicationInstance)
        .Container
          . AddNewExtension<Interception>()
          .Configure<Interception>()
            .SetInterceptorFor<T>(new VirtualMethodInterceptor())
        .Container
          .Resolve<T>();
    }

Ресурсы

Sapphire.Application – для чего всё это реализовывалось http://github.com/butaji/Sapphire/tree/master/trunk/Sapphire.Application/

Дэвид предлагает реализации связывания с данными следующего поколения “Databinding 3.0” на основе аналогичного подхода http://weblogs.asp.net/davidfowler/archive/2009/11/13/databinding-3-0.aspx

Ноябрь 16, 2009. Метки: , , , , , , . .net, IoC, Sapphire, sharepoint. Оставить комментарий.

Скринкаст о Test-Driven SharePoint Development

Записал скринкаст о том, как разрабатывал Sapphire REPL WebPart.

Октябрь 27, 2009. Метки: , , , , , , . Uncategorized. Оставить комментарий.

REPL WebPart для SharePoint

Intro

logoСегодня я расскажу о прототипе первого компонента под ярлычком Sapphire. Это REPL WebPart. Эта веб-часть предназначенная для производства оперативных изменений на серверной стороне SharePoint, так же для удаленного исполнения скриптов и тестирования некоторых кусков кода.

PreBody

Производство данной веб-части было инициированно в довольно таки частых потребностях исполнения серверного кода с достаточной оперативностью, в недоступности средств разработки под рукой.

Здесь есть небольшая презетнация, в которой я постарался отобразить принципы работы Repl WebPart:

В добавок к слайдам расскажу о том, что веб-часть представляет собой классический хостинг Dynamic Languages Runtime языков, пока из которых доступен только Python.

Body

Далее хотелось поговорить о том, как же всё это у меня получилось, итак проект включает в себе несколько основных модулей:

  • Веб-часть и контролы представления
  • Хостинг языков

Далее о них поподробнее

Language Hosting

В связи с тем, что языков, которые я захочу реализовать в данном проекте является неограниченное множество, то конечно же мне необходима абстрактная фабрика для их создания, которая будет скрывать иерархию всех доступных языков и инкапсулировать их под интерфейсом:

  public interface ILanguagesFactory
  {
    ILanguage Create(string name);
  }

  public interface ILanguage
  {
    string Name { get}

    object Execute(string input);

    void SetVar(string name, object value);
    
    object GetVar(string name);
  }

Отлично, далее к нашему проекту присоединяются сборки, необходимые для имплементации скриптовых языков:

Всё готово для того, чтобы реализовать Python, как среду для исполнения кода, отлично, приступим:

  public class PythonLanguage : ILanguage
  {
    private readonly ScriptScope _scope;
    
    public string Name
    {
      get { return «Python»}
    }

    public PythonLanguage()
    {
      _scope = Python.CreateEngine().CreateScope();
    }

    public object Execute(string input)
    {
      ScriptSource source = _scope.Engine.CreateScriptSourceFromString(input);
      return source.Execute(_scope);
    }
  }

Далее немного усложним задачу, в связи с тем, что нам будет необходимо реализовать контекст для работы с SharePoint, выглядеть это должно примерно так:

    [Test]
    private void python_should_assume_sharepoint_variables()
    {
      SPWeb fakeWeb = Isolate.Fake.Instance<SPWeb>();
      Isolate.WhenCalled(() => fakeWeb.Title).WillReturn(«I’m fake web»);
      var python = _factory.Create(«Python»);
      python.SetVar(«__x__»«123″);
      python.SetVar(«__web__», fakeWeb);
      python.Execute(«__x__ = __web__.Title»);
      var x = (string)python.GetVar(«__x__»);
      Assert.AreEqual(x, «I’m fake web»);
    }

Для работы с объектами SharePoint в из IronPython, нам необходимо добавить несколько библиотек:

      _scope.Engine.Runtime.LoadAssembly(typeof(string).Assembly);
      _scope.Engine.Runtime.LoadAssembly(typeof(Uri).Assembly);
      _scope.Engine.Runtime.LoadAssembly(typeof(SPList).Assembly); 

Это будет основой нашей работы с динамическими языками

WebPart + WebControls

Создадим проект с помощью SPVisualDev, добавим в него feature, внутри которой создадим веб-часть Repl WebPart, всё остальные действия стандартные, однако есть небольшой нюанс, нам нужен будет объект, с помощью которого можно будет выводить строковые значения после исполнения. Я решил создать для этих целей объект с классическим названием Console, его реализация предельна проста:

  public class Console
  {
    private readonly StringBuilder _messageBuilder = new StringBuilder();

    public void Write(object message)
    {
      _messageBuilder.Append(message);
    }

    public void WriteLine(object message)
    {
      _messageBuilder.AppendLine(message.ToString());
    }

    public string Message
    {
      get
      {
        return _messageBuilder.ToString();
      }
    }
  }

Мы будем передавать его в среду исполнения языков, а после исполнения кода опрашивать его свойство Message и выводить его содержимое в нашу веб-часть.

EndBody

Все исходники проекта доступны на github: http://github.com/butaji/Sapphire

Так же предварительную версию Sapphire.Environment (решение поставляется в WSP) можно слить на CodePlex: http://sapphire.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34895

Октябрь 24, 2009. Метки: , , , , . .net, C#, DLR, Python, sharepoint, tdd. 1 комментарий.

Кратко о Patterns & Practices: SharePoint Guidance

Интро

clip_image001

В данной статье я хочу произвести обзор руководства под названием “SharePoint Guidance” от подразделения Microsoft patterns & practices. Данное руководство предназначено разработчикам/архитекторам SharePoint, в нём описаны основные принципы построения систем на данной платформе. Над руководством трудились выдающиеся представители разработки под SharePoint, а так же он упорно держится в списке самых активных проектов на CodePlex. Далее чуть подробнее.

Описание руководства

Руководство фактически состоит из нескольких аспектов:

  1. SharePoint Guidance Library – библиотека наиболее используемых и полезных функций, таких как управление конфигурацией, абстрагирование слоя данных, логирование событий и сервисная инфраструктура
  2. Документация, в которой подробно описаны все принципы построения приведенных примеров, а так же руководства по основным вопросам, возникающим в разработке на SharePoint.
  3. Contoso Partner Portal Reference Implementation – показательное приложение на MOSS некоей компании Contoso, являющее собой экстранет-портал, в приложении используются практики наиболее приближенные к промышленным решениям.
  4. Contoso Training Management Reference Implementation – простое приложение HR-отдела, демонстрирующее базовые принципы построения решений на WSS.
  5. QuickStarts – два небольших примера самых простых приложений на SharePoint, а так же доступа к данным

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

image

Обзор руководства

1ая версия вышла в прошлом году (Dec2008), в настоящее время доступна 2ая версия данного руководства (Aug2009), о ней и будет идти речь.

  • Introduction – небольшое введение, а так же рекомендации к инструментам разработки: VSeWSS, U2U CAML Query Builder, CAML.NET, Typemock Isolator
  • Developing SharePoint Applications – основные сценарии разработки под платформу, а так же её ключевые возможности
  • Design and Development Guidelines – отображены ключевые моменты архитектуры SharePoint, а так же описаны подходы решения тех или иных задач разработки под платформу; описаны рекомендации к управлению жизненным циклом проектов
  • Application and Design Patterns – одна из наиболее интересных глав, в ней описаны как классические паттерны построения корпоративных приложений ложатся на решения под SharePoint
  • The SharePoint Guidance Library – описание библиотеки со всеми ключевыми возможностями и компонентами для разработки
  • Integrating Line-of-Business Systems – описание интеграции с существующими корпоративными системами
  • Considerations for Content-Driven Applications – здесь можно узнать о том, как правильно строить приложения, для хранения контента
  • Considerations for Enterprise-Scale Applications – рекомендации по созданию приложений масштаба предприятия
  • Considerations for Extranet Development – рекомендации по разработке и планированию экстранет-порталов
  • Partner Portal Reference Implementation – описание построения приложения-примера для MOSS
  • Training Management Reference Implementation– описание построения приложения-примера для WSS
  • QuickStarts – описание приложения для легкого старта работы с SharePoint

Критика

logo Данное руководство содержит в себе большое количество практичной полезной информации, однако в некоторых технических решениях моя точка зрения расходится с его создателями, в связи с чем мною был начат проект Sapphire: SharePoint Application Framework, который будет так же являться каркасом для построения решений на SharePoint, а так же включать примеры решений и необходимые в повседневной разработке компоненты.

Ресурсы по SharePoint Guidance

Скачать полную версию за август 2009 года можно здесь:

SharePoint Guidance так же представлен на CodePlex: http://www.codeplex.com/spg/ здесь можно задать интересующие вопросы и скачать все последние изменения.

Так же некоторые главы из SharePoint Guidance представлены в видеоряде на channel 9:

Ресурсы по SharePoint

TechNet располагает огромным количеством статей и книг по SharePoint, конечно в них не так много внимания уделено именно разработке, однако для формирования вижна платформы весьма полезно: http://technet.microsoft.com/en-us/library/cc262788.aspx

SharePoint Developer Center здесь можно найти практически всё, что нужно для разработки на SharePoint

Октябрь 19, 2009. Метки: , , . .net, Sapphire, patterns & practices, sharepoint. Оставить комментарий.

Habrahabr, Live Writer и Code Highlighting

Интро

Уже практически полгода я пользуюсь Windows Live Writer в качестве инструмента для написания веб-ориентированных статей. Это отличный инструмент, работающий с большим количеством blogengine’ов, и даже с SharePoint. Но разговор не об этом, в связи с тем, что я разработчик, мне частенько приходится вставлять листинг кода в написанные статьи, на это я и хочу обратить ваше внимание.

Пигменты

Многие представители Python-сообщества наверняка знакомы с дивным проектом под названием Pygments:

Ну так вот, товарищ Harry Pierson (@DevHawk) скомпилировал этот движок под IronPython и написал обертку-плагин для Windows Live Writer (качать здесь не торопиться). Отлично, однако то, что получается в результате его обработки не выделяется цветом на habrahabr, это связанно с некоторыми особенностями ресурса, однако поправимо.

Данными работами я и предлагаю заняться, для этого нам понадобятся:

После того, как мы скачали исходники, стоит разыскать скрипт под именем pygments_package\devhawk_formatter.py и немного его подкоректировать:

            # a style item is a tuple in the following form:
            # colors are readily specified in hex: ’RRGGBB’
            if style['color']:
                start += ‘<span style=»color:#%s«>’ % style['color']
                end = ‘</span>’ + end

заменить на

            # a style item is a tuple in the following form:
            # colors are readily specified in hex: ’RRGGBB’
            if style['color']:
                start += ‘<font color=»#%s«>’ % style['color']
                end = ‘</font>’ + end

Далее пересобрать с помощью скрипта build.bat проект и запустить инсталлер – теперь то что делает данный проект в  цвете отображается на хабре.

Октябрь 17, 2009. Метки: , , . .net, Blog, Live, Python. 1 комментарий.

Вы подготовились к приходу AutoMapper?

Введение

Данная статья предназначена к прочтению разработчикам и архитекторам распределенных систем на платформе .NET. В ней будет рассмотрен гибкий каркас для объектно-объектного преобразования (далее маппинга). Так же будут рассмотрены некоторые аспекты Domain-Driven Design’а.

Зачем мне нужен объектно-объектный маппинг?

Следуя основным принципам DDD, мы реализуем так называемую Rich Domain Model (эти объекты также должны соответствовать принципу POxO). Объекты реального мира, нашедшие отражение в нашем приложении частенько так же передают достаточную сложность, следовательно, достаточно корректно построенная модель крайне тяжело поддаётся перемещению между слоями приложения (не путать с легкостью вносимых изменений).

Data Transfer Object Тем не менее достаточно часто появляется необходимость “распределения” (я имею ввиду создание промежуточных сущностей, а не растекание модели по слоям) модели между слоями, для отображения, к примеру, атрибутов её сущностей пользователям (в шаблонах представления MVx), а так же передаче по сервисам (Data Transfer Object). Порой бывает даже, что модель “распределяется” для тестирования некоторых аспектов.

Предположим, мы в Африке, у нас банановая плантация, всё классно, выращиваем, продаём, выращиваем, продаём, но тут внезапно внутренний рынок переполняется и нам надо расширятся (к примеру вести бананы в Россию), мы пишем WCF сервис, который будет слать наши бананы. Так как бананы в Африке имеют несколько иное значение, чем в России, то, соответственно нам понадобятся лишь некоторые атрибуты (остальные фактически не имеют значения), которые мы забубеним в наш DTO

Правильнее было бы дать классу BananaWrapper название BananaDTO, для того, чтобы точно отображать его функциональное назначение, но я оставлю название таким для большего уровня абстракции, к примеру, если нам понадобится сделать автомат по продажи бананов и поместить этот объект в Presenter Model

Хочу заметить, что порой задача преобразования объектов становится довольно-таки нетривиальной и в лучшем случаем выглядит примерно подобным образом (это решение в лоб, есть ещё более изощренные методы ;) ):

  1. public class Banana
  2. {
  3. public string Country { get; set; }
  4. public double Price { get; set; }
  5. public int Age { get; set; }
  6. }
  7. public class BananaWrapper
  8. {
  9. public string Country { get; set; }
  10. public double Price { get; set; }
  11. public int Age { get; set; }
  12. }
  13. public class BananaMapper
  14. {
  15. public BananaWrapper GetWrapper(Banana banana)
  16. {
  17. return new BananaWrapper
  18. {
  19. Country = banana.Country,
  20. Price = banana.Price,
  21. Age = banana.Age
  22. };
  23. }
  24. }

* This source code was highlighted with Source Code Highlighter.

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

AutoMapper

И тут на сцену выходит наш персонаж – AutoMapper, и сразу же говорит мне: – послушай, ты что такое пишешь? тебе не лень? ты не боишься допустить ошибок? хочешь я тебе помогу?!. Я конечно же соглашаюсь, и получаю в ответ следующее решение моей проблемы:

  1. public class BananaMapper
  2. {
  3. public BananaMapper()
  4. {
  5. Mapper.CreateMap<Banana, BananaWrapper>();
  6. }
  7. public BananaWrapper GetWrapper(Banana banana)
  8. {
  9. return Mapper.Map<Banana, BananaWrapper>(banana); ;
  10. }
  11. }

* This source code was highlighted with Source Code Highlighter.

Класс, и это действительно всё, что мне понадобится. Сложность, вышележащего примера снизилась в моих глазах до нуля.

Итак, что же за механизмы лежат внутри AutoMapper?

AutoMapper проверяет есть соответствующие поля в указанных типах, соответствие проводится как по имени свойства, так и по его типу. Даже такие нюансы, как Product.Name и ProductName будут учтены и обработаны автоматически (wow!). Плюс ко всему методы GetXXX() будут ложится на свойства XXX (да, ну и естественно для особо раздражительных все эти прелести можно отключить и переопределить всё в своих собственных таблицах соответствия (далее мапках)).

Кастомная конфигурация выглядит примерно следующим образом:

  1. Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
  2. .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.EventDate.Date))
  3. .ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.EventDate.Hour))
  4. .ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.EventDate.Minute));

* This source code was highlighted with Source Code Highlighter.

Кстати, все ваши кастомные конфигурации легко поддаются проверке с помощью следующего метода:

  1. Mapper.AssertConfigurationIsValid();

* This source code was highlighted with Source Code Highlighter.

Так же не плохо работает с:

История

Проект появился в конце’08-начале’09, около полугода находился в версии 0.31, сейчас же добрался до RC 1.0, думаю, что релиз уже совсем скоро.

Overhead?

banana Дебаты по поводу того, насколько быстрее будет работать AutoMapper и присвоение свойств в ручную (и прочие мульки) я игнорирую, т.к. готов пойти на любые жертвы производительности, если получу ясный, читабельный код. Ах, да, автор AutoMapper позаботился об этих вопросах и написал бенчмарки, смотреть здесь: http://code.google.com/p/automapperhome/source/browse/#svn/trunk/src/Benchmark

Ресурсы

Скачать проект, а так же ознакомиться с исходными кодами можно здесь: http://code.google.com/p/automapperhome/

Обсуждения каркаса здесь: http://groups.google.com/group/automapper-users

Так же примеры использования есть здесь: http://automapper.codeplex.com/

Кстати проект разрабатывает Jimmy Bogard, который так же пишет BDD фреймворк для .NET под названием NBehave.

Октябрь 8, 2009. Метки: , , , . .net, DDD, architecture. 3 comments.

DynamicObject, JSON и ближайшее будущее

Введение

В данной статье хочу ознакомить вас с небольшим приложением для работы с JSON данными, демонстрирующим возможности, доступные нам в .NET 4.0. Поверхностно будут рассмотрены вопросы JSON-формата, а так же работы с динамическими типами данных.

JSON

Есть такая классная шутка, известная широким массам:

3763158824_e2f57810c4[1] JSON (JavaScript Object Notation) – простой формат обмена данными, удобный для чтения и написания как человеком, так и компьютером. Он основан на подмножестве языка программирования JavaScript, определенного в стандарте ECMA-262 3rd Edition – December 1999. JSON – текстовый формат, полностью независимый от языка реализации, но он использует соглашения, знакомые программистам C-подобных языков, таких как C, C++, C#, Java, JavaScript, Perl, Python и многих других. Эти свойства делают JSON идеальным языком обмена данными. далее…

JSON и ваше приложение

Ну так вот, обычно, получая объекты по JSON в наших приложениях мы должны подготовить инфраструктуру для их поддержки (к примеру с помощью DataContractJsonSerializer и решения на типа этого). Однако это занимает значительное время у разработчика. В связи с этим у меня появилось страстное желание поставить JSON механизмы на рельсы динамических возможностей .NET 4.0 и получать от работы с ним одно удовольствие ;)

DynamicObject

DynamicObject – Предоставляет нам простой класс, наследуясь от которого мы можем получить динамическое поведение объекта на этапе исполнения. Наследуясь от этого класса и переопределяя некоторые его методы реализуется вся основная логика необходимая нам для этого.

Если хостинг DLR и прочие прелести вас заинтересовали и вы хотите ознакомиться немного поглубже с вопросом, то можно посмотреть наше выступление здесь, а так же слайды (здесь и здесь).

К разработке

Для того, чтобы не испытывать неудобств при работе с JSON, я предлагаю воспользоваться (слить и зареференсить) решением от James Newton под названием JSON.NET, данный проект свободен и удовлетворяет всем основным требованиям работы с JSON в рамках .NET-стека (в том числе и LINQ).

Да, к тому же нам понадобится IDE, умеющая работать с .NET 4.0b1, к примеру Visual Studio 2010 Beta 1 (кстати #develop не отстает).

Создаем наше приложение, которое будет выглядеть примерно следующим образом:

string input = @»{CPU: ’Intel’, Drives: ['DVD read/writer', 
""500 gigabyte hard drive""  ]}»
;

dynamic computer = new DynamicJSON(input);

И пробуем посмотреть, какие же свойства обнаружатся у нашего компьютера:

>> computer.CPU
«Intel»

>> computer.Drives
[
  "DVD read/writer",
  "500 gigabyte hard drive"
]

>> computer.Drives[0]
«DVD read/writer»

Пока ничего необычного, учитывая, что мы не знаем, что же из себя представляет DynamicJSON, к реализации которого мы и обратимся за впечатлениями:

  using Newtonsoft.Json.Linq;

  public class DynamicJSON : DynamicObject
  {
    private JObject _data;

    public DynamicJSON(string data)
    {
      _data = JObject.Parse(data);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
      result = _data[binder.Name];
      return true;
    }
  }

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

Сентябрь 21, 2009. Метки: , , , , , . .net, DLR, JSON, dynamic. 1 комментарий.

Как забыть про ярлыки на рабочем столе?

Введение

image Раньше у меня довольно часто возникала проблема захламления рабочего стола огромным количеством ярлыков, и я начинал теряться в них, соответственно терять время при поиске необходимых мне приложений. В дальнейшем я научился пользоваться сочетанием клавиш win+r, создавая ярлыки с короткими именами в system32. С приходом Windows Vista (7) теперь только кнопки win, однако гибкость и настройка данных методов весьма ограниченна. Имеется так же огромное количество hotkey-менеджеров, однако не с одним из них я так и не сдружился.

Лаунчеры

Недавно (по-моему после прочтения книги «Продуктивный программист. Как сделать сложное простым, а невозможное – возможным» Нила Форда) мой интерес пал на launcher’ы. Для windows-платформы я нашёл несколько:

Ну и герой этого поста:

Немного истории

enso_321[1]

Изложу настолько, насколько я сумел разобраться в ней. Первоначально Enso был строго коммерческим проектом, разрабатываемым компанией Humanized (основанной Джеффри Раскиным, в котрой в последующем работал его сын). В дальнейшем компания начала работу над Mozilla Ubiquity (аналог Enso, являющийся плагином для FireFox), что позволило ей сделать Enso бесплатным.

Enso

Лучше 1 раз увидеть, чем 7 раз прочитать, базовые возможности представлены в следующих роликах:

На настоящий момент на сайте компании есть две версии продукта:

удобна в эксплуатации, но умеет делать лишь базовые вещи.

настройка (как и во второй версии) происходит через embeded веб-сервер

в данной версии появилось огромное количество очень полезных плагинов (к примеру поиск в google, генерация объектов-карт по выделенному адресу) однако юзабили немного упало (с моей точки зрения) в плане того, что после ввода команды начала открываться отдельная строка для ввода параметров, на что уходило время, и приходилось нажимать лишний раз enter

Все отлично, за исключением того, что проект на данном сайте вроде как заброшен, что не совсем воодушевляло к использованию, однако слазив внутрь и посмотрев реализацию, обнаружилось, что всё написано на Python (межплатформенность?), а так же исходники доступны в свободном доступе, что немного приободрило.

В дальнейших поисках упоминаний о Enso я наткнулся на коммунити http://www.ensowiki.com, а так же (самое главное) хостинг нынешей версии Enso https://launchpad.net/enso, итак, что же изменилось с тех времен:

  • настройка больше не через веб-сервер
  • межплатформенность (Windows, Linux, Mac OS X, etc)
  • интерфейс первой версии
  • практически все плагины из второй версии

Используем Enso

Для установки существует инсталлер, поэтому трудности вряд ли могут встретиться. Далее у меня возникла необходимость в настройке (теперь для совершения настроек существует файл enso\config.py) “основной” клавиши (Caps Lock) в режим залипания (Sticky в терминологии создателей программы), для этого я проделал следующее:

# Whether the Quasimode is actually modal («sticky»).

IS_QUASIMODE_MODAL = True

Расширяем Enso

Классно, мой питомец (Enso) теперь стал послушным и ласковым, однако хочется научить его понимать новые команды, ну что ж, пускай это будет Enso hello world.

Я отправился в папку commands в корне, куда добавил файл butaji.py со следующим содержимым:

import enso.config

from enso.messages import displayMessage

def cmd_butaji(ensoapi, cmd):

if cmd == «time»:

ensoapi.display_message(«Hello world»)

cmd_butaji.valid_args = ['time']

И у меня получилось следующее:

image

image

Великолепно! я думаю, что мы с Enso очень сдружимся.

Сентябрь 7, 2009. Метки: , , , , . Productive, Python. 3 comments.

Ещё раз о SharePoint Guidance

Небольшая заметка, в которой я в очередной раз хотел бы обратить внимание на следующий документ:

sharepoint_guidance[1]

patterns & practices SharePoint Guidance

исключительно рекомендую всем разработчикам SharePoint

А так же вчера на http://channel9.msdn.com/ вышло несколько роликов, о работе с эти проектом:

How to use the logging components? – p & p Developing SharePoint Applications guidance

How to use the configuration component? – p & p Developing SharePoint Applications guidance

How to use the SharePoint Service Locator? – p & p Developing SharePoint Applications guidance

Walkthrough of the Contoso Reference Implementation- p & p Developing SharePoint Applications guidance

Приятного просмотра.

Сентябрь 3, 2009. Метки: , , , . sharepoint. Оставить комментарий.

Следующая страница »