代码之家  ›  专栏  ›  技术社区  ›  Steffen

如何实例化内部私有类的privateType

  •  5
  • Steffen  · 技术社区  · 15 年前

    我试图为一个私有的内部类设置一个单元测试,但几乎没有成功:

    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:无法加载类型”

    我做错了什么?

    据我所知,privateType是基于反射的,我想它非常适合这种情况,因为您不能在名称空间的正下方有一个私有类。

    编辑:

    添加了DailyStatkey的完整实现。我要测试的是gethashcode方法的唯一性。如你所见,我试图将日期+类型调整为单个int。

    4 回复  |  直到 11 年前
        1
  •  6
  •   zemien    14 年前

    我自己找到了一个解决方案:

    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);
    
        2
  •  5
  •   Jake Arnaldo237    11 年前

    您也可以直接使用privatetype:

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

    嵌套类具有不同于其命名空间(s t a t s.model.dailystat.dailystatkey)的字符串格式,因此用法并不明显。

        3
  •  1
  •   aqwert    15 年前

    因为它是私有的,所以唯一可以创建实例的类是 DailyStat 本身。除非您让它成为非私有反射(activator),否则如果您想创建该类,它将是您唯一的选择,尽管这不是一个好主意,因为除非您能够将它强制转换为足够公共的类型或接口,否则您将无法直接使用它。

    编辑:

    既然您正试图为单元测试做这项工作,那么实际上您不应该测试这个类,因为它是私有的。您只能通过 戴利斯塔 .

        4
  •  -2
  •   x77    15 年前

    您可以在父类上对公共的“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();