Ответы пользователя Чак Норрис - CodeHelper

Чак Норрис

Чак Норрис
Карма 3384
Имя Неизвестно
Возраст Неизвестно
Сайт Неизвестно
Twitter Неизвестно
Участвует в проекте 1105 дн., 12 час., 34 мин.
Последняя активность 536 дн., 21 час., 25 мин. назад
О себе ничего не указано

Ответы

Новые Лучшие
1
...
5
6
7
8
9
...
12
Перейти к вопросу →

Самый простой способ — подписаться на событие BeginRequest в файле Global.asax и в теле обработчика выполнить все необходимые действия:

void Application_BeginRequest(object sender, EventArgs e)
{
    HttpContext context = HttpContext.Current;
    string currentLocation = context.Request.Path.ToLower();
    string rewritedLocation = GetRewritedLocation(currentLocation); 1
    if (currentLocation != rewritedLocation)
    {
        context.RewritePath(rewritedLocation); 2
    }
}

1 — метод GetRewritedLocation содержит логику подмены (код не приводится);

2 — собственно, подмена URL.

Поскольку код из Global.asax сложно тестировать и повторно использовать, то лучшим решением будет реализация той же логики в http-модуле (IHttpModule). В коде модуля, как и в коде Global.asax, можно подписаться на событие начала обработки запроса и выполнить аналогичную подмену.

Перейти к вопросу →

В MSDN описано понятие Version Tolerant Serialization (VTS), которое обозначает сериализацию, «терипимую» к изменению версии.

Version Tolerant Serialization — это набор фич, включенных в .NET Framework 2.0, которые облегчают внесение изменений в сериализуемые классы. VTS доступно для классов, помеченных атрибутом SerializableAttribute. Благодаря VTS можно добавлять новые поля к классам без нарушения совместимости с сериализованными данными предыдущих версий. Фичи VTS работают когда используется BinaryFormatter и частично работают для SoapFormatter.

В частности VTS позволяет добавить свойства в класс и при этом:

  1. старые версии приложения смогут работать с новой версией сериализованного класса, игнорируя неизвестное поле (Tolerance of Extraneous or Unexpected Data).
  2. новые версии приложения смогут десериализовать старые классы, задавая пропущенным свойствам значения по умолчанию (Tolerance of Missing Data).

Пункт 1 работает из коробки, а вот для пункта 2 нужно пометить соответствующее поле атрибутом OptionalFieldAttribute:

[Serializable]
public class Customer
{
    public string FirstName;

    public string LastName;

    [OptionalField]
    public string Country;
}

Атрибут OptionalFieldAttribute имеет свойство VersionAdded, которое хранит порядковый номер версии файла (начиная с 2). Каждый раз при добавлении нового свойства в класс нужно помечать это поле атрибутом OptionalFieldAttribute и указывать версию изменения.

Если при десериализации не удается найти значение какого-то из свойств/полей, то этому свойству/полю присваивается значение по умолчанию. Чтобы изменить такое поведение нужно использовать специальные атрибуты, позволяющие реагировать на события (де)сериализации:

  • OnDeserializingAttribute — отмечается метод, который будет вызван перед десериализацией;
  • OnDeserializedAttribute — отмечается метод, который будет вызван после десериализацией;
  • OnSerializingAttribute — отмечается метод, который будет вызван перед сериализацией;
  • OnSerializedAttribute — отмечается метод, который будет вызван после сериализацией;

Пример использования:

[Serializable]
public class Customer
{
    public string FirstName;

    public string LastName;

    [OptionalField]
    public string Country;

    [OnDeserializing]
    private void ResetCountry (StreamingContext sc)
    {
        Country = "Россия";
    }
}

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

Перейти к вопросу →

Из официальной документации:

Fluent NHibernate предоставляет альтернативу стандартным XML-файлам конфигурации меппинга NHibernate. Вместо написания XML документов (.hbm.xml), Fluent NHibernate позволяет вам писать меппинг в строго типизированной форме, на языке C#. Это обеспечивает легкость рефакторинга, улучшает читабельность и локаничность кода.

Простой пример

Обычная конфигурация NHibernate:

<?xml version="1.0" encoding="utf-8" ?>  
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  
  namespace="QuickStart" assembly="QuickStart">  

  <class name="Cat" table="Cat">  
    <id name="Id">  
      <generator class="identity" />  
    </id>  

    <property name="Name">  
      <column name="Name" length="16" not-null="true" />  
    </property>  
    <property name="Sex" />  
    <many-to-one name="Mate" />  
    <bag name="Kittens">  
      <key column="mother_id" />  
        <one-to-many class="Cat" />  
      </bag>  
  </class>  
</hibernate-mapping>

Конфигурация с использованием Fluent NHibernate:

public class CatMap : ClassMap<Cat>
{
  public CatMap()
  {
    Id(x => x.Id);
    Map(x => x.Name)
      .Length(16)
      .Not.Nullable();
    Map(x => x.Sex);
    References(x => x.Mate);
    HasMany(x => x.Kittens);
  }
}

Как видно из примера, правила меппинга описываются в конструкторе класса-наследника ClassMap<>. Для определения конкретных правил используются методы Id, Map, References и тп, а также методы-расширения, позволяющие писать fluent-конструкции. Чтобы меппинг вступил в силу нужно соответствующим образом настроить SessionFactory:

private static ISessionFactory CreateSessionFactory()
{
  return Fluently.Configure()
    .Database(
      SQLiteConfiguration.Standard
        .UsingFile("firstProject.db")
    ) 1
    .Mappings(m => 2
      m.FluentMappings.AddFromAssemblyOf<Program>())
    .BuildSessionFactory();
}

Fluent NHibernate позволяет задавать настройки источника данных 1 и указать классы меппинга 2.

Перейти к вопросу →

Правила каскадирования задаются атрибутом cascade в конфигуровочном файле. Возможные варианты cascade:

none — не использовать никаких автоматических правил, в этом случае ответственность за целостность данных лежит на пользователе и движке БД.

save-update — когда объект сохраняется или обновляется, проверяются и создаются/обновляются все зависимые объекты (если это необходимо).

delete — при удалении объекта удаляются все ассоциированные с ним объекты.

delete-orphans - при удалении объекта удаляются все ассоциированные с ним объекты. В дополнение к этому, когда дочерний объект A удаляется из списка ассоциированных объектов родителя B (B.ListOfA.Remove(A)) и не назначается другому родителю (так называемый orphaned объект), то A также удаляется вместе с B.

all — когда объект сохраняется, обновляется или удаляется, проверяются и создаются/обновляются/добавляются все зависимые объекты (если это необходимо). Аналогично совместному применению правил delete и save-update.

all-delete-orphans - когда объект сохраняется, обновляется или удаляется, проверяются и создаются/обновляются/добавляются все зависимые объекты (аналогично all). В дополнение к этому, когда дочерний объект A удаляется из списка ассоциированных объектов родителя B (B.ListOfA.Remove(A)) и не назначается другому родителю, то A также удаляется вместе с B.

Внимание! В разных версиях NHibernate может использоваться разное написание слова orphans (orphans или orphan). Если получаете исключение типа

Unsupported cascade style: delete-orphans

то это ваш случай.

Перейти к вопросу →

Синтаксис NVelocity идентичен Velocity для Java (за исключением расширений, поддерживаемых разными реализациями). Поэтому можно использовать те же инструменты, что и для Java версии. Например, для редактора jEdit есть простенькое расширение подсветки синтаксиса Velocity. И, конечно, есть соответствующие плагины для всех популярных Java (см Velocity and Development Tools)

Перейти к вопросу →

Есть интересный способ работы с XML. Нужно создать XSD схему для документа, затем с помощью xsd.exe сгенерировать классы, соответствующие xml-структуре. После этого можно использовать стандартный XmlSerializer для загрузки/сохранения объектов.

Перейти к вопросу →

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

Перейти к вопросу →

Классический способ — использовать XmlDocument

Открываем файл:

XmlDocument doc = new XmlDocument();
doc.Load("test.xml");

Выбираем узлы или атрибуты, используя запросы XPath:

// Выбираем единичный узел.
XmlNode node = doc.DocumentElement.SelectSingleNode("/foo/bar");
// Выбираем все узлы по запросу.
XmlNode[] nodes = doc.DocumentElement.SelectNodes("/foo/bar");

Или обращаемся напрямую к классам XmlDocument, XmlNode и тп

Перейти к вопросу →

Сonvention over Сonfiguration — это принцип построения фреймворков и библиотек, призванный сократить количество требуемой конфигурации без потери гибкости. Обычно переводится как «соглашения по конфигурации». В строгой форме этот принцип можно выразить так: аспект программной системы нуждается в конфигурации тогда и только тогда, когда этот аспект НЕ удовлетворяет некоторой спецификации. Принцип работает когда речь идет о меппинге классов на какие-либо ресурсы (таблицы базы данных, события, ресурсы файловой системы). Согласно принципу, если класс соответствует соглашению наименования, тогда он не нуждается в дополнительной конфигурации. В этом контексте название принципа можно перевести как «Соглашение НАД конфигурацией», такой перевод указывает на первостепенность соглашения, а не конфигурации.

Классический пример CoC принципа — Hibernate. В Hibernate правила объектно-реляционного меппинга можно описывать с помощью XML-файлов:

<class name="Tag" table="tag">
    <property name="Name" column="name"/>        
    <property name="Value" column="value"/>        
    <property name="Value2" column="value2"/>
    <property name="Value3" column="value3"/>
</class>

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

<class name="Tag">
    <property name="Name"/>        
    <property name="Value"/>        
    <property name="Value2"/>
    <property name="Value3"/>
</class>

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

Наибольшее применение принцип CoC находит в среде Ruby on Rails. Это в принципе понятно, если учесть, что ror ориентирована на быструю разработку, а coc позволяет свести конфигурацию к минимуму.

Перейти к вопросу →

Скандально известная фича RenderAction. Это набор extension-методов (файл ChildActionExtensions), позволющих виду «отрисовывать» внутри себя результат работы любого экшена. Выглядит это примерно так:

<%Html.RenderAction("Controller", "Action"); %>

Как уже упоминалось, эта возможность заимствована из Ruby, откуда она была выкинута всилу своей порочности.


1
...
5
6
7
8
9
...
12
v1.7.123.556
© 2009—2010 CodeHelper FAQ | О сайте | Обратная связь | История изменений | Статьи
Creative Commons LicenseМатериалы сайта распространяются под лицензией Creative Commons Attribution-Share Alike 3.0 Unported.