Страницы

четверг, 17 ноября 2011 г.

Конфликт имён. И как с ним бороться.

Проблема - конфликт имён. 
 
  Однажды, в обычный рабочий день писал unit-тест для проверки работы Windsor-interceptor'ов с помощью Moq. Код выглядел примерно так:
var system = new Mock<ISystem>();
var windsor = new WindsorContainer();

windsor.Register(
  Component.For<ISystem>()
    .Instance(system.Object)
    .Interceptors(typeof (SomeInterceptor)));

var resolvedSystem = windsor.Resolve<ISystem>();

var proxy = (IProxyTargetAccessor) resolvedSystem;
  В ответ компилятор вполне определённо намекает:

 Error    1    The type 'Castle.DynamicProxy.IProxyTargetAccessor' exists in both 'd:\Projects\Test\packages\Castle.Core.3.0.0.2001\lib\net40-client\Castle.Core.dll' and 'd:\Projects\Test\packages\Moq.4.0.10827\lib\NET40\Moq.dll' 
  
  Дело в том, что в Moq интегрирована сборка Castle.DynamicProxy. Дописать namespace не поможет - имена совпадают полностью. Аналогичная проблема возникает и в случае Rhino.Mocks. Огорчительно, но к счастью, решение есть.


Решение - Alias. 

  Если посмотреть свойства любого reference в проекте, можно заметить одно волшебное свойство:

  По-умолчанию значение этого свойства global. Что оно означает? В некотором смысле, это самый глобальный namespace, с которого компилятор начинает поиск зависимостей. Т.е. такой код вполне компилируется и рабоает:
var windsor = new global::Castle.Windsor.WindsorContainer();
  Так вот, в свойствах reference можно присвоить зависимости другой alias.  Поменяем для Moq название на Moq.
  Теперь в коде мы можем ссылаться на этот псевдоним. Для этого служит ключевое слово extern alias. Для этого служит ключевое слово extern alias. Добавить его следует в самое начало файла:
extern alias Moq;
using Moq::Moq;
  Вторая строка выглядит несколько странно, но я объясню: это обычный using, но с указанием alias'a библиотеки. (другие using мы можем писать global::System.Text и т.д., но компилятор разрешает нам опустить global).
  Таким же образом можно использовать несколько версий одной библиотеки. Хотя и не рекомендовал бы этого делать. 

  Пожалуй, стоит упомянуть о самом главном - недостатках. Если для reference указан alias - то в каждом файле, где он используется придётся писать extern alias. Поэтому подумайте хорошенько, что какую именно библиотеку надо переименовать.

Комментариев нет:

Отправить комментарий