How to instantiate PrivateType of inner private class

柔情痞子 提交于 2019-12-04 19:31:28

问题


I was trying to setup a unit test for a private inner class, but had very little success:

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

I tried this code:

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

as well as

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

To no avail.

The assembly's name is "Stats.Model", and to me the type name looks correct too, but I just get an exception: "System.TypeLoadException: Could not load type"

So what am I doing wrong ?

PrivateType, to the best of my knowledge, is reflection based, and I'd guess it's pretty much intended for this scenario, as you cannot have a private class directly beneath a namespace.

EDIT:

Added full implementation of DailyStatKey. What I want to test is the uniqueness of my GetHashCode method. As you can see I try to fit a date + type into a single int.


回答1:


Found a solution myself:

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:


You can also use PrivateType directly as well:

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

Nested classes have a string format that's different from their namespace (which is Stats.Model.DailyStat.DailyStatKey) so the usage isn't obvious.




回答3:


Since it is private the only class that can create the instance is DailyStat itself. Unless you make it non private reflection (activator) would be your only choice if you want to create the class although that would not be a good idea as you wont be able to use it directly unless you are able to cast it to a public enough type or interface

EDIT:

Since you are trying to do this for unit testing then effectively you shouldnt test this class as it is private. You would only be able to test it through any public interface of DailyStat.




回答4:


You can code a public "GetDailyStatKey" method on parent class.

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

Now you can write:

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


来源:https://stackoverflow.com/questions/3200875/how-to-instantiate-privatetype-of-inner-private-class

工具导航Map