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(…)”。很公平,我明白了:-)