Как отлить прокладку в виде бетона?

У меня есть прокладка на основе ClassA.PropertyB, где PropertyB имеет тип ClassB. ClassA является внутренним и находится в другой сборке из моего тестового проекта. Я добавил ссылку в AssemblyInfo.cs, чтобы это внутреннее можно было увидеть в моем тестовом проекте, и я могу создать прокладку.

Я хотел бы отправить экземпляр shimClassB в ClassA через конструктор:

public ClassA(object someInstance)
{
  PropertyB = (ClassB)someInstance;
} 

Вышеприведенное вызывает InvalidCastException:

Unable to cast object of type shimClassB to type ClassB.

Есть ли какой-нибудь другой метод, который поместит экземпляр прокладки в ClassA?


person 4thSpace    schedule 07.03.2014    source источник


Ответы (2)


Важно отметить, что ClassB и ShimClassB не имеют отношения класса, производного от базового класса. Таким образом, броски, которые вы делаете, могут быть не совсем такими, как вы ожидаете. Вы видите, что неявные преобразования работают из-за пользовательских преобразований, предоставленных Microsoft.Fakes.

Ваш ShimClassB наследуется от ShimBase<T>, где T равно ClassB. Этот класс имеет метод, который вводит определяемое пользователем неявное преобразование между ShimClassB и ClassB.

public static implicit operator T(ShimBase<T> shim)

Когда вы пытаетесь сделать.

public ClassA(object someInstance)
{
    PropertyB = (ClassB)someInstance;
} 

у вас не может быть приведения к ClassB, так как между object и ClassB не определено преобразование.

Из спецификации языка программирования С# 6.2.4 Явные преобразования ссылок:

Для успешного явного преобразования ссылки во время выполнения значение исходного операнда должно быть нулевым или фактический тип объекта, на который ссылается исходный операнд, должен быть типом, который может быть преобразован в целевой тип с помощью неявной ссылки. преобразование (§6.1.6) или преобразование бокса (§6.1.7). Если явное преобразование ссылки не удается, создается исключение System.InvalidCastException.

Вы обнаружите, что если бы ваш код имел промежуточное приведение, он больше не выдавал бы InvalidCastException, однако это не окончательное решение, поскольку вы не хотите приведения к Shim в своем конструкторе:

public ClassA(object someInstance)
{
    PropertyB = (ClassB)(ShimClassB)someInstance;
} 

Чтобы решить эту проблему. Я бы посоветовал изменить ваш конструктор ClassA так, чтобы он был типизирован и не принимал object, когда вы передаете свой shimClassB в этот конструктор, вы обнаружите, что будет использоваться определяемое пользователем неявное преобразование:

// The user-defined implicit conversion takes care of this for us
ClassA(shimClassB); 

public ClassA(ClassB someInstance)
{
  PropertyB = someInstance;
} 

или если вы хотите сохранить свой конструктор как есть:

ClassA((ClassB)shimClassB); 

public ClassA(object someInstance)
{
  PropertyB = (ClassB)someInstance;
} 
person Martin    schedule 11.03.2014

Я не вижу никаких проблем с этим. Убедитесь, что ваше свойство имеет правильный тип, или попробуйте присвоить некоторый объект ShimClassB новой переменной типа ClassB.

Может быть полезно показать нам свой код, хотя я только что попробовал точно такой же пример без каких-либо исключений.

person Dennis Kassel    schedule 07.03.2014