Как создать экземпляр PrivateType для внутреннего частного класса - PullRequest
5 голосов
/ 08 июля 2010

Я пытался настроить модульный тест для закрытого внутреннего класса, но безуспешно:

namespace Stats.Model
{
  public class DailyStat
  {
    private class DailyStatKey // The one to test
    {
      private DateTime date;
      public DateTime Date 
      { 
        get { return date; }
        set { date = value.Date; }
      }

      public StatType Type { get; set; }

      public override int GetHashCode()
      {
        return Date.Year * 1000000 +
               Date.Month * 10000 +
               Date.Day * 100 +
               (int)Type;
      }

      public override bool Equals(object obj)
      {
        DailyStatKey otherKey = obj as DailyStatKey;
        if (otherKey == null)
          return false;
        return (this.Date == otherKey.Date && this.StatType == otherKey.StatType);
      }
    }
  }
}

Я попробовал этот код:

PrivateType statKeyType = new PrivateType("Stats.Model", "Stats.Model.DailyStat.DailyStatKey");

а также

PrivateType statKeyType = new PrivateType("Stats.Model", "DailyStat.DailyStatKey");

Безрезультатно.

Имя сборки "Stats.Model", и для меня имя типа тоже выглядит правильно, но я получаю исключение: "System.TypeLoadException: Could not load type"

Так что я делаю не так?

PrivateType, насколько мне известно, основан на рефлексии, и я предполагаю, что он в значительной степени предназначен для этого сценария, поскольку вы не можете иметь закрытый класс непосредственно под пространством имен.

EDIT:

Добавлена ​​полная реализация DailyStatKey. То, что я хочу проверить, это уникальность моего метода GetHashCode. Как видите, я пытаюсь вписать тип date + в один int.

Ответы [ 4 ]

6 голосов
/ 08 июля 2010

Сам нашел решение:

var parentType = typeof(DailyStat);
var keyType = parentType.GetNestedType("DailyKeyStat", BindingFlags.NonPublic); 
//edited to use GetNestedType instead of just NestedType

var privateKeyInstance = new PrivateObject(Activator.CreateInstance(keyType, true));

privateKeyInstance.SetProperty("Date", DateTime.Now);
privateKeyInstance.SetProperty("Type", StatType.Foo);

var hashCode = (int)privateKeyInstance.Invoke("GetHashCode", null);
5 голосов
/ 28 марта 2014

Вы также можете напрямую использовать PrivateType:

PrivateType statKeyType = new PrivateType("Stats.Model", "Stats.Model.DailyStat+DailyStatKey");

Вложенные классы имеют строковый формат, который отличается от их пространства имен (которое является Stats.Model.DailyStat.DailyStatKey), поэтому использование не очевидно.

1 голос
/ 08 июля 2010

Так как это private, единственный класс, который может создать экземпляр, это DailyStat.Если вы не сделаете это не частным отражением (активатор) будет вашим единственным выбором, если вы хотите создать класс, хотя это не будет хорошей идеей, так как вы не сможете использовать его напрямую, если не сможете привести его к общедоступномутип или интерфейс

РЕДАКТИРОВАТЬ:

Поскольку вы пытаетесь сделать это для модульного тестирования, то фактически вы не должны тестировать этот класс, поскольку он является закрытым.Вы сможете протестировать его только через любой общедоступный интерфейс DailyStat.

0 голосов
/ 08 июля 2010

Вы можете закодировать открытый метод "GetDailyStatKey" в родительском классе.

public class DailyStat
{
    private class DailyStatKey // The one to test 
    {
    }
    public DailyStatKey GetDailyStatKey()
    {
        return new  DailyStatKey();
    }
}

Теперь вы можете написать:

DailyStat v = new DailyStat();
var x =  v.GetDailyStatKey();
...