Неявное / явное преобразование по отношению к ключевому слову «как»
Я пытаюсь провести какое-то модульное тестирование в проекте, который, к сожалению, имеет высокий уровень взаимозависимости модулей. В настоящее время многие наши классы обращаются кUserIdentity объект для определения аутентификации, но этот объект имеет много внутренних скачков, которые я бы так же быстро избегал при попытке проверить функциональность отдельных модулей.
Чтобы обойти это, я пытаюсь создать «фиктивную» версию этого UserIdentity, которую можно подключить к более жестко контролируемой переменной среде.
Короче говоря, у нас есть класс UserIdentity с несколькими общедоступными свойствами только для чтения и статическим CurrentIdentity (IIdentity) заполнитель. Я могу обойти почти все с "насмешкой"IIdentity реализации, но я наталкиваюсь на стену, когда достигаю точки, где CurrentIdentity приводится какUserIdentity.
Это довольно простой метод:
internal static UserIdentity GetCurrentIdentity()
{
UserIdentity currentIdentity = ApplicationContext.User.Identity as UserIdentity;
return currentIdentity;
}
Я создал свой фиктивный объект, чтобы создать членаUserIdentity введите, а затем сделайте что-то вроде этого:
public static implicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
или это
public static explicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
Проблема в том, что, насколько я могу судить, это «как» не вызывает ни явной, ни явной операции преобразования моего фиктивного объекта. Мой (ые) вопрос (и): я пропускаю что-то простое здесь или это не сработает, потому что (я предполагаю) операция 'as' смотрит прямо на наследование классов (что мой объект не делает ...) ?
Кроме того, может быть, немного не по теме, но почему в классе не может быть одновременных явных и неявных операторов одного и того же результирующего типа? Если я не пропустил что-то глупое, компилятор не работает, если я пытаюсь использовать оба оператора преобразования одновременно. Я должен выбрать один или другой.
ОБНОВИТЬ
Хорошо, теперь я полностью сбит с толку. Может быть, я становлюсь неаккуратным, но я попытался сделать прямое приведение, и я не могу заставить это работать. Я прочитал об операторе в MSDN, и в примере показан оператор, идущий в результирующий класс, а не в исходный класс, но я не уверен, имеет ли это значение или нет (я пробовал оба места в коде ниже). В любом случае, я пытался установить простой тестовый стенд, чтобы увидеть, что я могу делать неправильно, но я тоже не могу заставить это работать ... Вот что у меня есть
class Program
{
// Shared Interface
public interface IIdentity { }
// "real" class (not conducive to inheritence)
public class CoreIdentity : IIdentity
{
internal CoreIdentity() { }
// Just in case (if this has to be here, that seems unfortunate)
public static explicit operator CoreIdentity(ExtendedIdentity src)
{
return src.Identity;
}
}
// "mock" class (Wraps core object)
public class ExtendedIdentity : IIdentity
{
public CoreIdentity Identity { get; set; }
public ExtendedIdentity()
{
Identity = new CoreIdentity();
}
// This is where the operator seems like it should belong...
public static explicit operator CoreIdentity(ExtendedIdentity src)
{
return src.Identity;
}
}
// Dummy class to obtain "current core identity"
public class Foo
{
public IIdentity Identity { get; set; }
public CoreIdentity GetCoreIdentity()
{
return (CoreIdentity)Identity;
}
}
static void Main(string[] args)
{
ExtendedIdentity identity = new ExtendedIdentity();
Foo foo = new Foo();
foo.Identity = identity;
CoreIdentity core = foo.GetCoreIdentity();
}
}
Но это вызывает следующее исключение, когда я вызываю foo.GetCoreIdentity ():
Невозможно привести объект типа «ExtendedIdentity» к типу «CoreIdentity».
и я не могу поймать ни один из моих явных операторов с точкой останова, так что похоже, что он делает это определение, даже не «пробуя» маршруты конвертации, которые я указал.
Конечно, я упускаю что-то очевидное. Помогает ли тот факт, что мой Identity (в Foo), определенный как IIdentity, как-то мешает разрешению приведения с использованием явных операторов реализующего типа? Это показалось бы мне странным.
ОБНОВЛЕНИЕ (# 2)
У меня такое чувство, что я спамую в своем сообщении со всеми этими обновлениями (возможно, я должен собрать свои действия, прежде чем быть настолько счастливым для триггера :)) В любом случае, я изменил метод GetCoreIdentityMethod моего Foo, чтобы сделать это вместо этого:
public CoreIdentity GetCoreIdentity()
{
ExtendedIdentity exId = Identity as ExtendedIdentity;
if (exId != null)
return (CoreIdentity)exId;
return (CoreIdentity)Identity;
}
и (после очистки неоднозначной ссылки, вызванной наличием оператора в обоих классах), он вошел в мой явный код оператора преобразования и работал должным образом. Поэтому я думаю, что это выглядит так, как будто явные операторы не разрешаются полиморфно (это правильное понимание?), И тот факт, что мое свойство было напечатано как IIdentity, а не как ExtendedIdentity, препятствовало тому, чтобы оно вызывало логику приведения, даже если это было Тип ExtendedIdentity во время его вызова. Это кажется мне очень странным и неожиданным ... и довольно неудачным.
Я не хочу переписывать хранитель объекта CurrentIdentity, чтобы он знал о моих специальных тестовых приведениях. Я хотел включить эту «особую» логику в сам макет, так что это действительно заставляет меня задуматься.