воскресенье, 16 июня 2013 г.

Выборочный Binding в Ninject

Постановка задачи

Предположим, у нас есть некоторый интерфейс
interface IMyInterface
{
}
И несколько его реализаций, разбросанных по разным сборкам
//Где-то в в какой-то сборке
class ImplementA : IMyInterface
{
}

//Где-то в в какой-то другой сборке
class ImplementB : IMyInterface
{
}
Всем сборкам доступен общий Kernel Ninject-а, через который мы будем биндить наши реализации
//В первой сборке
kernel.Bind<IMyInterface>().To<ImplementA>();
//Во второй сборке
kernel.Bind<IMyInterface>().To<ImplementB>();
Запрашиваться реализации тоже могут в разных местах кода. В том числе и разными разработчиками. Для примера, будем запрашивать их так:
var res = kernel.GetAll<IMyInterface>();
foreach( var item in res )
{
   Console.WriteLine( item.GetType().Name );
}
А теперь, собственно, наша задача - как сделать так, что бы мы получили не все реализации, а только определенные, соответствующие определенным критериям?

пятница, 14 июня 2013 г.

Закладки из ToolStrip-а

Преамбула

Однажды, работая с классическим TabControl-ем, мне понадобилось разместить закладки слева от контента (сверху у меня был ToolBar и закладки там были не в тему). Продолбавшись пару часов Исследуя данный вопрос, я осознал, что TabControl работает без глюков только в стандартном режиме. Стоит хоть что-то поменять и баги лезут изо всех щелей. После чего я стал копаться по форумам и нашел интересное решение - ToolStrip. В самом деле, кнопочки ToolStripButton во многом похожи на закладки - достаточно слегка изменить их визуальную часть и прикрутить разработать логическую составляющую. Еще немного покопавшись в интернете, я нашел несколько готовых вариантов. Однако, все они были "сырыми" и требовали доработок. После чего я, взяв за основу то, что сделали до меня, стал писать свой вариант. В настоящий момент прошло уже более года с тех пор, как я успешно использую эту систему. А значит, ее можно считать более-менее отлаженной и пришло время сделать ее общественным достоянием.

Общее описание

воскресенье, 2 июня 2013 г.

Как сравнить строки с "*" и "?"

Зачастую встает задача сравнить две строки с использованием так называемых "wildcard" - спецсимволов "*" (произвольное количество любых символов) и "?" (один любой символ). Конечно, есть регулярные выражения. Но что если маску должен задавать пользователь, а в сложных выражениях просто нет необходимости. На этот случай я сделал себе маленький класс-помощник. Выкладываю тут - вдруг, еще кому пригодится.
public static class StringHelper
{
   static bool CompareWithPart( string source, string part )
   {
      if( source.Length != part.Length )
         return false;
      for( int i = 0; i < source.Length; i++ )
         if( source[i] != part[i] && part[i] != '?' )
            return false;
      return true;
   }

   static bool ConsumePart( ref string source, string part, bool first, bool last )
   {
      if( part == string.Empty )
      {
         if( last ) source = "";
         return !(first && last);
      }
      if( last )
      {
         var subStr = first ? source : source.Substring( Math.Max( 0, source.Length - part.Length ) );
         source = "";
         return CompareWithPart( subStr, part );
      }
      if( first )
      {
         var len = Math.Min( part.Length, source.Length );
         var subStr = source.Substring( 0, len );
         source = source.Substring( len );
         return CompareWithPart( subStr, part );
      }
      for( int i = 0; i <= source.Length - part.Length; i++ )
         if( CompareWithPart( source.Substring( i, part.Length ), part ) )
         {
            source = source.Substring( i + part.Length );
            return true;
         }
      return false;
   }

   public static bool CompareWildcard( this string source, string mask )
   {
      if( source == null )
         throw new ArgumentNullException( "source" );
      if( mask == null )
         throw new ArgumentNullException( "mask" );
      var parts = mask.Split( '*' );
      for( int i = 0; i < parts.Length; i++ )
         if( !ConsumePart( ref source, parts[i], i == 0, i == parts.Length - 1 ) )
            return false;
      return true;
   }

   public static bool CompareWildcard( this string source, string mask, bool ignoreCase )
   {
      if( source == null )
         throw new ArgumentNullException( "source" );
      if( mask == null )
         throw new ArgumentNullException( "mask" );
      return ignoreCase
         ? source.ToLower().CompareWildcard( mask.ToLower() )
         : source.CompareWildcard( mask );
   }

}
Использовать этот класс очень просто. Например так:
Console.WriteLine( "Мама моет раму".CompareWildcard( "*раму" ) );
Console.WriteLine( "Мама моет раму".CompareWildcard( "Мама*" ) );
Console.WriteLine( "Мама моет раму".CompareWildcard( "*моет*" ) );
Есть вопросы? Пишите в комментарии.