2) Создайте такой метод, как {{X0}}, который инициализирует хранилище учетных записей, но в вашем тесте имитируйте этот метод:
public class Key
{
private readonly string _name;
public Key(string name)
{
_name = name;
}
public string Name
{
get { return _name; }
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if (GetType() != obj.GetType()) return false;
Key other = (Key)obj;
return Name == other.Name;
}
public override int GetHashCode()
{
return GetType().GetHashCode() ^ _name.GetHashCode();
}
public override string ToString()
{
return GetType() + "(" + Name + ")";
}
}
Различные ключи:
public class CarKey : Key
{
public CarKey(string name)
: base(name)
{
}
}
public class VanKey : CarKey
{
public VanKey(string name)
: base(name)
{
}
}
public class CoupeKey : CarKey
{
public CoupeKey(string name)
: base(name)
{
}
}
Бен Флинн прав в том, что вам нужен способ ввести IDictionary<Key, Data>
в объект, который вы тестируете. Два дополнительных способа сделать это:
IDictionary<Key, Data> dict;
public Data MostRelevantData(Key key)
{
if(dict.Contains(key)) return dict[key];
//try base class of key (with the same name) recursively
throw new KeyNotFound();
}
Можно ли реализовать MostRelevantData
без рефлексии? Не стесняйтесь изменять дизайн классов Key
, если это упростит задачу.
РЕДАКТИРОВАТЬ: Пример:
dict[new Key("A")] = "Data A";
dict[new CarKey("B")] = "Data B";
dict[new CoupeKey("B")] = "Data B1";
dict[new CoupeKey("C")] = "Data C";
MostRelevantData(new CoupeKey("B"));//returns "Data B1"
MostRelevantData(new CoupeKey("A"));//returns "Data A"
MostRelevantData(new CoupeKey("C"));//returns "Data C"
MostRelevantData(new CarKey("C"));//throws
MostRelevantData(new CarKey("B"));//returns "Data B"
MostRelevantData(new VanKey("C"));//throws
MostRelevantData(new VanKey("B"));//returns "Data B"
2 ответа
Вы можете добавить метод к Key
для получения экземпляра базового ключа:
public class Key
{
public virtual Key GetBaseKey()
{ return null; }
}
public class CarKey : Key
{
public override Key GetBaseKey()
{ return new Key(this.Name); }
}
Возможно более быстрое решение, чем AjV
public Data MostRelevantData(Key key)
{
while(key != null)
{
if(dict.Contains(key)) return dict[key];
key = key.GetBaseKey();
}
throw new KeyNotFound();
}
Обратной стороной является то, что вам придется эффективно дублировать ключевую иерархию в каждом подклассе.
GetBaseKey
как невиртуального метода в Key
.
В myClass methodToTest выглядит так:
public static class DictionaryExtensionMethods
{
public static T MostRelevantData<T>(this IDictionary<Key, T> dict, Key key)
{
if (dict.ContainsKey(key))
{
return dict[key];
}
Key relevantKey = dict.Keys.FirstOrDefault(
loop => key.IsRelevant(loop));
if (relevantKey != null)
{
return dict[relevantKey];
}
throw new KeyNotFoundException();
}
}
Очевидно, однако, чтобы это работало, вам необходимо реализовать Key.IsRelevant
. К счастью, это тоже довольно просто, любезно предоставлено Type.IsSubclassOf:
public class Key
{
public bool IsRelevant(Key other)
{
return (this.GetType().IsSubclassOf(other.GetType()))
&& (this.Name == other.Name);
}
}
Я новичок в OCMockObjects и пытаюсь имитировать метод экземпляра класса ACAccount:
public class PolymorphicKeysTests
{
public PolymorphicKeysTests()
{
}
private Dictionary<Key, string> dict;
[TestInitialize]
public void TestInitialize()
{
dict = new Dictionary<Key, string>();
dict[new Key("A")] = "Data A";
dict[new CarKey("B")] = "Data B";
dict[new CoupeKey("B")] = "Data B1";
dict[new CoupeKey("C")] = "Data C";
}
[TestMethod]
public void CoupeKeyB()
{
Assert.AreEqual("Data B1", dict.MostRelevantData(new CoupeKey("B")));
}
[TestMethod]
public void CoupeKeyA()
{
Assert.AreEqual("Data A", dict.MostRelevantData(new CoupeKey("A")));
}
[TestMethod]
public void CoupeKeyC()
{
Assert.AreEqual("Data C", dict.MostRelevantData(new CoupeKey("C")));
}
[TestMethod]
[ExpectedException(typeof(KeyNotFoundException))]
public void CarKeyC()
{
dict.MostRelevantData(new CarKey("C"));
}
[TestMethod]
public void CarKeyB()
{
Assert.AreEqual("Data B", dict.MostRelevantData(new CarKey("B")));
}
[TestMethod]
[ExpectedException(typeof(KeyNotFoundException))]
public void VanKeyC()
{
dict.MostRelevantData(new VanKey("C"));
}
[TestMethod]
public void VanKeyB()
{
Assert.AreEqual("Data B", dict.MostRelevantData(new VanKey("B")));
}
}
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.
Type
? Можете ли вы привести пример, как вы хотите использовать этот код?CoupeKey
сName
"ASDF" не найден, Grzenio хотел бы, чтобы он увидел, есть ли какие-либо другие объектыCarKey
сName
"ASDF" (то есть он может вернутьVanKey
, который имеет тот же "ASDF"Name
). (Не уверен, как бы вы определили, является лиVanKey
более релевантным, чем, скажем,SedanKey
, хотя, если бы оба имели совпадающееName
)Dictionary<Key, Data> dict
, а другойDictionary<string, List<Key>> NameLookup
. Всякий раз, когда вы добавляетеKey
, вы сохраняете запись вNameLookup
. Когда ключи добавляются с соответствующими именами, они будут заполнять соответствующие спискиList<Key>
. Когда вы выполняете поиск, еслиKey
не существует вdict
, вы можете выполнить вторую проверку вNameLookup
; если там есть дополнительные совпаденияKeys
, вы можете вытащить их соответствующиеData
изdict
.