C# 如何实例化内部私有类的PrivateType

C# 如何实例化内部私有类的PrivateType,c#,unit-testing,private-members,C#,Unit Testing,Private Members,我试图为一个私有内部类设置单元测试,但几乎没有成功: namespace Stats.Model { public class DailyStat { private class DailyStatKey // The one to test { private DateTime date; public DateTime Date { get { return date; } set { date

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

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中。

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

编辑:

既然您试图为单元测试这样做,那么实际上您不应该测试这个类,因为它是私有的。您只能通过
DailyStat
的任何公共接口对其进行测试

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

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

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);

您也可以直接使用PrivateType:

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

嵌套类的字符串格式与其命名空间(Stats.Model.DailyStat.dailystakey)不同,因此用法不明显。

这是不可能的,因为您返回的类型对调用方不可见。另外,如果需要的话,您可以将DailyStatKey设置为public。就像Dykam说的那样,它不起作用,而且我可以使用一个公共的内部类——我真的不想要。您可以在内部类上放置一个公共的接口,这样您就可以控制对用户可见的内容world@aqwert,这有什么好处?你也可以在类本身中限制曝光。嗯,但是PrivateType确实使用反射AFAIK,所以我仍然不明白为什么这是一个问题。此外,如果不是这个,PrivateType是做什么的?您不能在命名空间中直接拥有私有类。您只能拥有私有的内部类,如果您希望封装只有外部类才会使用的功能,则这些内部类非常有用。只能在编写新PrivateType()的类中使用它。不涉及任何影响。我提到了反射,因为它可以用来安装私有类和调用classIt之外的私有方法,这正是为了封装在外部类中庄严使用的功能。那部分没问题。我将检查PrivateType是否在外部类中工作;var keyType=parentType.NestedType(“DailyKeyStat”,BindingFlags.NonPublic);像一个符咒一样工作:-)@apollodude217:没想过,它现在已经发布了,我会在2天期限结束后接受它。在C#中,“new SomeType(args)”不使用反射。相反,它总是一个构造函数调用,并调用一个可用的构造函数。在您的示例代码中,没有构造函数,因此唯一可用的构造函数是默认构造函数(null构造函数——不带参数的构造函数)。您也不能从外部调用它,因为该类是私有的。所以你需要反思是对的。相关问题:我不太清楚你为什么提到关于构造函数的部分?关于使用反射的PrivateType,我的意思是它使用反射来访问私有类/方法。(这在MSDN页面上非常明显:因为它需要ReflectionPermission。至于相关的问题,我知道不应该测试私有类,但是因为它只在内部使用,而且GetHashCode总是返回一些唯一的东西是至关重要的,所以我想我最好做一个测试。哦!你是对的。我误读了代码。我是认为你出于某种原因放了“新DailyStatKey(…)”。很公平,我明白了:-)