<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Техно-логи &#187; c#</title>
	<atom:link href="http://www.kurdyukov.com/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kurdyukov.com</link>
	<description>Заметки о разработке и прочей жизни</description>
	<lastBuildDate>Sat, 04 Feb 2012 01:34:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Автоматическая реализация INotifyPropertyChanged на Spring.NET</title>
		<link>http://www.kurdyukov.com/2012/02/04/spring-inotifypropertychanged/</link>
		<comments>http://www.kurdyukov.com/2012/02/04/spring-inotifypropertychanged/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 01:34:55 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Spring.NET]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=188</guid>
		<description><![CDATA[В статье ранее я писал как сделать автоматическую реализацию INotifyPropertyChanged на основе расширений библиотеки NInject. К сожалению, моя жизнь с этой библиотекой не сложилась, NInject был заменен на Spring.NET. При этом схему автореализации надо было как-то перенести без особенных изменений прикладного кода. Объясню, что именно я сделал. Для начала нам нужен интерфейс, который будет реализовываться [...]]]></description>
			<content:encoded><![CDATA[<p>В статье <a href="http://www.kurdyukov.com/2012/01/31/aop-inotifypropertychanged/" title="Простая реализация INotifyPropertyChanged" target="_blank">ранее</a> я писал как сделать автоматическую реализацию INotifyPropertyChanged на основе расширений библиотеки NInject. К сожалению, моя жизнь с этой библиотекой не сложилась, NInject был заменен на Spring.NET. При этом схему автореализации надо было как-то перенести без особенных изменений прикладного кода. Объясню, что именно я сделал.</p>
<p><span id="more-188"></span><br />
Для начала нам нужен интерфейс, который будет реализовываться всеми потенциальными автонотифицируемыми классами:</p>
<pre class="brush: csharp; title: ; notranslate">
    public interface IAutoNotifyPropertyChanged : INotifyPropertyChanged
    {
        void OnPropertyChanged(string propertyName);
    }
</pre>
<p>Удобства ради можно использовать базовый класс для всех авто-реализаций:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class ViewModelBase : IAutoNotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
</pre>
<p>Кроме этого, нам понадобятся атрибуты, которыми мы будет включать/отключать авто-нотификацию:</p>
<pre class="brush: csharp; title: ; notranslate">
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class NotifyOfChangesAttribute : Attribute
    {
    }
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class DoNotNotifyOfChangesAttribute : Attribute
    {
    }
</pre>
<p>Теперь пришла очередь Pointcut, которые будет определять setter-ы целевых свойств:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class AutoNotifyPointcut : StaticMethodMatcherPointcut
    {
        public override bool Matches(MethodInfo method, Type targetType)
        {
            if (!typeof(IAutoNotifyPropertyChanged).IsAssignableFrom(targetType))
                return false;

            // non-setters ignored
            if (!method.Name.StartsWith(&quot;set_&quot;))
                return false;

            object[] attributes = targetType.GetCustomAttributes(typeof(NotifyOfChangesAttribute), true);
            if (attributes.Length &gt; 0)
            {
                object[] disables = method.GetCustomAttributes(typeof (DoNotNotifyOfChangesAttribute), true);
                if (disables.Length &gt; 0)
                    return false;

                return true;
            }

            attributes = method.GetCustomAttributes(typeof (NotifyOfChangesAttribute), true);
            return attributes.Length &gt; 0;
        }
    }
</pre>
<p>Затем нам нужен advice, в котором и будет происходить вся работа:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class AfterPropertySetAdvice : IMethodInterceptor
    {
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();

        public object Invoke(IMethodInvocation invocation)
        {
            object proxy = invocation.Proxy;
            string name = null;

            IAutoNotifyPropertyChanged model = proxy as IAutoNotifyPropertyChanged;
            if (model == null)
            {
                logger.Error(&quot;Advice is called on non-IAutoNotifyPropertyChanged class&quot;);
            }
            else
            {
                name = invocation.Method.Name;
                if (!name.StartsWith(&quot;set_&quot;))
                {
                    logger.Error(&quot;Cannot notify on non-setter&quot;);
                }
                name = name.Substring(4);
            }

            object rval = invocation.Proceed();

            if (name != null)
            {
                model.OnPropertyChanged(name);
            }

            return rval;
        }
    }
</pre>
<p>Тут для вящего удобсва отладки используется NLog. Его использование можно вовсе удалить.</p>
<p>Так, классы созданы, надо как-то их применить к объектам. Сразу скажу, что из-за особенностей Spring AOP для оборачивания класса в advice надо, чтобы экземпляр класса создавался Spring-ом. Код подключения выглядит примерно так:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;objects xmlns=&quot;http://www.springframework.net&quot;&gt;
  &lt;object id=&quot;notifyOnChangePointcut&quot; type=&quot;CommonControls.AutoNotify.AutoNotifyPointcut, CommonControls&quot;/&gt;
  &lt;object id=&quot;afterPropertySetAdvice&quot; type=&quot;CommonControls.AutoNotify.AfterPropertySetAdvice, CommonControls&quot;/&gt;

  &lt;object id=&quot;notifyInterceptor&quot; type=&quot;Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop&quot;&gt;
    &lt;property name=&quot;Pointcut&quot; ref=&quot;notifyOnChangePointcut&quot;/&gt;
    &lt;property name=&quot;Advice&quot; ref=&quot;afterPropertySetAdvice&quot;/&gt;
  &lt;/object&gt;

  &lt;object type=&quot;Spring.Aop.Framework.AutoProxy.InheritanceBasedAopConfigurer, Spring.Aop&quot;&gt;
    &lt;property name=&quot;ProxyDeclaredMembersOnly&quot; value=&quot;false&quot;/&gt;
    &lt;property name=&quot;ObjectNames&quot;&gt;
      &lt;list&gt;
        &lt;value&gt;*Model&lt;/value&gt;
      &lt;/list&gt;
    &lt;/property&gt;
    &lt;property name=&quot;InterceptorNames&quot;&gt;
      &lt;list&gt;
        &lt;value&gt;notifyInterceptor&lt;/value&gt;
      &lt;/list&gt;
    &lt;/property&gt;
  &lt;/object&gt;
&lt;/objects&gt;
</pre>
<p>Можно заметить, что оборачиванию будут подвергнуты объекты, id которых заканчивается на &laquo;Model&raquo;. Анонимные объекты будет проигнорированы.</p>
<p>Кажется, что ограничение по имени какое-то странное. Также кажется, что использование InheritanceBasedAopConfigurer выглядит странно в контексте наличия тега aop:config в Spring.NET. Поясню, почему именно так.</p>
<p>В рамках Spring.NET существует 3 способо создания proxy объектов для вызова advice:</p>
<ol>
<li>Aggregation based &#8211; для объекта-обертки генерируется DynamicProxy со своим интерфейсом. Такой объект нельзя привести к оригинальному типу target объекта. Реальный объект в этом случае будет аггрегирован внутри proxy. Нам не подходит из-за несовместимого интерфейса.</li>
<li>Inheritance based &#8211; объект-прокси будет наследником класса target объекта, при этом обернуты будут только virtual методы и свойства оригинала. Оригинальный объект будет аггрегирован внутри proxy. В нашем случае это дает интересный спец-эффект: поскольку события тоже проксируются, то добавление обработчика события на объект-обертку не влияет на оригинальный объект. Значит, если внутри advice вызвать событие, то вызов будет превращен в вызов объекта-оригинала, а не обертки. А на внутреннем объекте обработчиков как небыло так и нет. Значит, тоже не подходит</li>
<li>InheritanceBasedAopConfigurer &#8211; новый способ генерации вызовов, добавленный в Spring 1.2. Идея состоит в изменении кода оригинального объекта. Вот это нам подходит, но дает указанные выше ограничения на создание объектов</li>
</ol>
<p>Пример создания объекта:</p>
<pre class="brush: xml; title: ; notranslate">
  &lt;object id=&quot;mainModel&quot; type=&quot;DataServer.ViewModel.RetranslatingDataServerManagerModel, DataServer&quot;/&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/02/04/spring-inotifypropertychanged/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Простая реализация INotifyPropertyChanged</title>
		<link>http://www.kurdyukov.com/2012/01/31/aop-inotifypropertychanged/</link>
		<comments>http://www.kurdyukov.com/2012/01/31/aop-inotifypropertychanged/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 01:10:34 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[INotifyPropertyChanged]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=168</guid>
		<description><![CDATA[При разработке для платформы .NET часто приходится делать так раздражающие всех реализации интерфейса INotifyPropertyChanged на классах-моделях. Типичный пример выглядит так: На мой взгляд, с этим кодом есть 2 проблемы: Очень много повторений и кода вызванного необходимостью вызвать NotifyPropertyChanged. Увеличивается количество &#171;тупой&#187; работы. Использование строковой константы Name в качестве аргумента. Рефакторинг может привести к разрушению биндинга [...]]]></description>
			<content:encoded><![CDATA[<p>При разработке для платформы .NET часто приходится делать так раздражающие всех реализации интерфейса <code>INotifyPropertyChanged</code> на классах-моделях. Типичный пример выглядит так:</p>
<pre class="brush: csharp; title: ; notranslate">
class StatisticsRecord: INotifyPropertyChanged
{
    private string name;
    public string Name { get { return name; } set { name = value; NotifyPropertyChanged(&quot;Name&quot;); } }	

    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
</pre>
<p>На мой взгляд, с этим кодом есть 2 проблемы:</p>
<ol>
<li>Очень много повторений и кода вызванного необходимостью вызвать <code> NotifyPropertyChanged</code>. Увеличивается количество &laquo;тупой&raquo; работы.</li>
<li>Использование строковой константы Name в качестве аргумента. Рефакторинг может привести к разрушению биндинга к такому свойству.</li>
</ol>
<p><span id="more-168"></span><br />
По счастью разработчики симпатичного фреймворка <a href="http://http://ninject.org/" title="http://ninject.org/" target="_blank">NInject</a> сделали расширение <a href="https://github.com/ninject/ninject.extensions.interception" title="https://github.com/ninject/ninject.extensions.interception" target="_blank">Ninject.Extensions.Interception</a>, которое позволяет решить описанные выше проблемы за счет использования динамического AOP. Используется это так:</p>
<ol>
<li>Подключаем к проекту библиотеки NInject, Ninject.Extensions.Interception, Castle.Core, Ninject.Extensions.Interception.DynamicProxy</li>
<li>Создаем класс-реализацию интерфейса IAutoNotifyPropertyChanged, например так:
<pre class="brush: csharp; title: ; notranslate">
public class ViewModelBase : IAutoNotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;

     public void OnPropertyChanged(string propertyName)
     {
         PropertyChangedEventHandler handler = PropertyChanged;
         if (handler != null)
         {
             handler(this, new PropertyChangedEventArgs(propertyName));
         }
     }
}
</pre>
</li>
<li>Используем этот класс в нашем классе модели. Например:
<pre class="brush: csharp; title: ; notranslate">
[NotifyOfChanges]
class StatisticsRecord: INotifyPropertyChanged
{
    public virtual string Name { get; set; }

    [DoNotNotifyOfChanges]
    public virtual string NonNotifyableProperty { get; set; }
}
</pre>
<blockquote><p><strong>NB!</strong> Важно, чтобы getter-ы и setter-ы были виртуальными, поскольку мы используем DynamicProxy для добавления нотификаций
</p></blockquote>
</li>
<li>Подключаем &laquo;перехватчик&raquo; при конфигурации ядра NInject:
<pre class="brush: csharp; title: ; notranslate">
...
kernel.Components.Add&lt;IPlanningStrategy, AutoNotifyInterceptorRegistrationStrategy&gt;();
...
</pre>
</li>
<p>Код стал короче и понятнее напорядок.</p>
<p>PS. Детали того, как именно это все устроено смотрите тут: <a href="http://innovatian.com/2010/01/ninject-extensions-interception-and-iautonotifypropertychanged-ianpc/" title="http://innovatian.com/2010/01/ninject-extensions-interception-and-iautonotifypropertychanged-ianpc/" target="_blank"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/01/31/aop-inotifypropertychanged/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>System.BadImageFormatException при загрузке тестов в ReSharper</title>
		<link>http://www.kurdyukov.com/2012/01/24/system-badimageformatexception-tests-resharper/</link>
		<comments>http://www.kurdyukov.com/2012/01/24/system-badimageformatexception-tests-resharper/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 22:31:01 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[ReSharper]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=161</guid>
		<description><![CDATA[В начале создания авто-тестов в одном проекте на C# начал возникать System.BadImageFormatException при попытке запуска тестов из ReSharper. Выяснение показало, что проблема была в том, что сборка с тестами имела Any CPU. А тестируемые классы были в EXE, который был собран в x86. При этом Windows используется 64х битный, следовательно Any CPU = x64. Решение [...]]]></description>
			<content:encoded><![CDATA[<p>В начале создания авто-тестов в одном проекте на C# начал возникать System.BadImageFormatException при попытке запуска тестов из ReSharper. Выяснение показало, что проблема была в том, что сборка с тестами имела Any CPU. А тестируемые классы были в EXE, который был собран в x86. При этом Windows используется 64х битный, следовательно Any CPU = x64.</p>
<p>Решение просто &#8211; указать в тестовой сборке целевую платформу x86. Это делается в закладке Build свойств проекта тестовой сборки.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/01/24/system-badimageformatexception-tests-resharper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Названия обработчиков событий в VS2010</title>
		<link>http://www.kurdyukov.com/2012/01/09/vs2010-handy/</link>
		<comments>http://www.kurdyukov.com/2012/01/09/vs2010-handy/#comments</comments>
		<pubDate>Mon, 09 Jan 2012 15:05:36 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[c#]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=152</guid>
		<description><![CDATA[После установки ReSharper на Visual Studio 2010 (всем разработчикам на C# рекоммендую, кста) наиболее активно разражает подсвечивание названий методов, который автоматически генерируются Visual Designer для обработки событий, поскольку название типа &#171;Form1_Load&#187; никак не соответствует идеям начинать название с глагола и не использовать &#171;_&#187;. Но это можно исправить. Есть 2 способа исправления проблемы. 1. Изменить способ [...]]]></description>
			<content:encoded><![CDATA[<p>После установки ReSharper на Visual Studio 2010 (всем разработчикам на C# рекоммендую, кста) наиболее активно разражает подсвечивание названий методов, который автоматически генерируются Visual Designer для обработки событий, поскольку название типа &laquo;Form1_Load&raquo; никак не соответствует идеям начинать название с глагола и не использовать &laquo;_&raquo;. Но это можно исправить.<br />
<span id="more-152"></span><br />
Есть 2 способа исправления проблемы.</p>
<p><strong>1. Изменить способ генерации названий методов</strong><br />
<em>Предпочтительный</em><br />
<a href="http://www.kurdyukov.com/wp-content/uploads/2012/01/screenshot.png"><img src="http://www.kurdyukov.com/wp-content/uploads/2012/01/screenshot.png" alt="" title="Настройки" width="250" height="249" class="alignright size-full wp-image-155" /></a><br />
Установить плагин <a href="http://visualstudiogallery.msdn.microsoft.com/14f62cb9-b559-4bad-9388-37da2150e238/?SRC=Home" target="_blank">EventHandler Naming</a>, который позволяет менять политику именования методов-обработчиков. Устанавливать можно прямо из Extension manager. Даже настройки не требует, по умолчанию настроен как <code>On${SiteName}${EventName}</code>, например, <code>OnForm1Load</code>. Если надо, настраивается.</p>
<p><strong>2. Настроить ReSharper, чтобы он не ругался</strong></p>
<ol>
<li>Идем в меню ReSharper | Options | Languages | C# | C# Naming Style</li>
<li>Переключаем на &laquo;Advanced settings&#8230;&raquo;</li>
<li>Меняем значение &laquo;Event subscriptions on fields&raquo; с умолчального <code>$object$_On$event$</code> на <code>$object$_$event$</code></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/01/09/vs2010-handy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VS.NET: интеграция с ANTLR</title>
		<link>http://www.kurdyukov.com/2009/02/11/vsnet-antlr/</link>
		<comments>http://www.kurdyukov.com/2009/02/11/vsnet-antlr/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 14:19:57 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[antlr]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[vs.net]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=16</guid>
		<description><![CDATA[Для разработки парсеров искусственых языков (ИЯ) часто используются различные инструменты генерации. Один из таких инструментов &#8211; ANTLR. Я использовал ANTLR в одном из проектов для разбора 2 специальных ИЯ. Проект делался на C# в среде VS.NET 2008. Среда ANTLRWorks являлась хоть и работающим, но очень неудобным решением. Недостатки использования ANTLRWorks были в следующем: Две различные [...]]]></description>
			<content:encoded><![CDATA[<p>Для разработки парсеров искусственых языков (ИЯ) часто используются различные инструменты генерации. Один из таких инструментов &#8211; <a href="http://www.antlr.org/">ANTLR</a>. Я использовал ANTLR в одном из проектов для разбора 2 специальных ИЯ. Проект делался на C# в среде VS.NET 2008. Среда <a href="http://www.antlr.org/works/index.html">ANTLRWorks</a> являлась хоть и работающим, но очень неудобным решением.</p>
<p><span id="more-16"></span>Недостатки использования ANTLRWorks были в следующем:</p>
<ol>
<li>Две различные среды для редактирование кода одного проекта.</li>
<li>Необходимость вручную запускать генерацию кода лексера и парсера при изменении грамматики.</li>
</ol>
<p>Качественное решение должно быть избавлено от этих недостатков.</p>
<p>Для работы с грамматиками ANTLR можно использовать плагин <a href="http://wiki.pixelminegames.com/index.php?title=Tools:nFringe:Antlr">nFringe ANTLR</a>. Плагин распространяется бесплатно и легко устанавливается на VS.NET 2008.</p>
<p>Теперь надо добавить в проект возможность автоматической перегенерации грамматики в процессе компиляции проекта через VS.NET. Делаем следующее:</p>
<p><strong>Подготовка окружения:</strong></p>
<ol>
<li>Убедиться, что на вашем компьютере установлена Java. Достаточно ввести в командной строке &laquo;java -version&raquo;, чтобы это проверить. Если не установлена &#8211; установить.</li>
<li>Установить текущую версию инструмента antlr.jar, он будет использоваться для генерации кода. На момент написания заметки текущая стабильная версия &#8211; 3.1.1. Версия, которая не требует java, существует, но находится в состоянии beta.</li>
<li>Закрыть проект</li>
<li>Найти файл .csproj, который описывает проект</li>
<li>Открыть его на редактирование (например, через notepad)</li>
</ol>
<p><strong>Изменение проекта</strong></p>
<p>Вставить следующий текст перед закрывающим тегом Project:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p16code3'); return false;">View Code</a> XML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p163"><td class="code" id="p16code3"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ItemGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Antlr3</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;SimpleCalc.g&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;OutputFiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>SimpleCalcLexer.cs;SimpleCalcParser.cs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/OutputFiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Antlr3<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Antlr3</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;BigCalc.g&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;OutputFiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>BigCalcLexer.cs;BigCalcParser.cs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/OutputFiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Antlr3<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ItemGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;GenerateAntlrCode&quot;</span> <span style="color: #000066;">Inputs</span>=<span style="color: #ff0000;">&quot;@(Antlr3)&quot;</span> <span style="color: #000066;">Outputs</span>=<span style="color: #ff0000;">&quot;%(Antlr3.OutputFiles)&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Exec</span> <span style="color: #000066;">Command</span>=<span style="color: #ff0000;">&quot;java -cp C:\Libs\ANTLR\antlr-3.1.1.jar org.antlr.Tool -message-format vs2005 @(Antlr3)&quot;</span> <span style="color: #000066;">Outputs</span>=<span style="color: #ff0000;">&quot;%(Antlr3.OutputFiles)&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;PropertyGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;BuildDependsOn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>GenerateAntlrCode;$(BuildDependsOn)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/BuildDependsOn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/PropertyGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p><strong>NB!</strong> Нужно заменить названия грамматик и названия выходных файлов, а также правильно указать местоположение файла antlr.jar.</p>
<p>Далее надо добавить зависимости лексера и парсера от грамматики. Находим упоминания файлов SimpleCalcLexer.cs и SimpleCalcParser.cs внутри тега ItemGroup, содержащего упоминания файла AssemblyInfo.cs. Если их нет, значит надо добавить. В результате упоминания этих файлов должны иметь вид:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p16code4'); return false;">View Code</a> XML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p164"><td class="code" id="p16code4"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Compile</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;SimpleCalcLexer.cs&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;AutoGen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/AutoGen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;DesignTime<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/DesignTime<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;DependentUpon<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>SimpleCalc.g<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/DependentUpon<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Compile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Compile</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;SimpleCalcParser.cs&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;AutoGen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/AutoGen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;DesignTime<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/DesignTime<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;DependentUpon<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>SimpleCalc.g<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/DependentUpon<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Compile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Теперь можно открыть проект и убедиться в том, что парсер и лексер будут перегенерированы.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2009/02/11/vsnet-antlr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

