Доступ к частному конструктору извне класса в C # - PullRequest
23 голосов
/ 12 ноября 2010

Если я определю класс с закрытым конструктором по умолчанию и открытым конструктором, который имеет параметры, как я могу получить доступ к закрытому конструктору?

public class Bob
{
   public String Surname { get; set; }

   private Bob()
   { }

   public Bob(string surname)
   {
      Surname = surname;
   }
}

Я могу получить доступ к приватному конструктору через статический метод класса следующим образом:

public static Bob GetBob()
{
   return new Bob();
}

Я думал, что могу получить доступ к приватному конструктору через метод расширения, поскольку (согласно моему пониманию) методы расширения переводятся так, что они кажутся статическими методами в классе, но я не могу:

static class Fred
{
   public static Bob Bobby(this Bob bob)
   {
      return new Bob();
   }
}

Итак,как я могу получить доступ к приватному конструктору?

Спасибо


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

Причина, по которой я хотел это сделать, заключалась в том, что я хотел создать тесты для одногонаших бизнес-классов, но не позволяют потребителю этого класса иметь возможность неправильно создать экземпляр объекта.Я тестирую его, поэтому я знаю (надеюсь!), При каких обстоятельствах тесты не пройдут.Я все еще тестирую n00b прямо сейчас, поэтому моя идея могла быть, а может и не быть, «неправильным» способом ведения дел.

Я изменил свою стратегию тестирования, чтобы просто делать то, что делает потребительэтот класс будет, то есть вызывать открытые методы и, если открытые методы в порядке, при условии, что закрытые методы в порядке.Я все еще предпочел бы проверить частные методы, но мой босс дышит мне в шею на предмете: - (

Ответы [ 7 ]

44 голосов
/ 12 ноября 2010

По умолчанию конструкторы являются закрытыми.Разработчик не делает его закрытым для развлечения.

Но если вы все еще хотите использовать конструктор по умолчанию, вы получите его с помощью отражения.

var constructor = typeof(Bob).GetConstructor(BindingFlags.NonPublic|BindingFlags.Instance, null, new Type[0], null);
var instance = (Bob)constructor.Invoke(null);

Редактировать

Я видел ваш комментарий о тестировании.Никогда не тестируйте защищенные или частные методы / свойства.Возможно, вы сделали что-то не так, если не можете протестировать эти методы / свойства с помощью открытого API.Либо удалите их, либо реорганизуйте класс.

Редактировать 2

Забыли флаг привязки.

2 голосов
/ 12 ноября 2010

В дополнение к ответу @ jgauffin, в котором рассказывается, как вызывать частные конструкторы с помощью отражения:

Можно ли изменить модификаторы приватного конструктора?

Кажется, вы реализуете Factory Pattern в своем коде. Таким образом, модификатор должен быть internal.

public class Product
{
   //others can't create instances directly outside the assembly
   internal Product() { }    
}
public class ProductProvider
{
   //they can only get standardized products by the provider
   //while you have full control to Product class inside ProductProvider
   public static Product CreateProduct()
   {
       Product p = new Product();    
       //standardize the product
       return p;
   }  
}

Методы расширения

public static MyExt
{
   public static void DoSomething(this Product p) { }
}

Вызов p.DoSomething() фактически равен MyExt.DoSomething(p). Он не помещает этот метод в класс Product.

2 голосов
/ 12 ноября 2010

Существует несколько способов решения этой проблемы:

Один : сделать конструктор общедоступным.Если вам нужен доступ к нему из-за пределов класса, почему он закрыт (возможно, вам нужен только частный конструктор для тестирования, и в этом случае это допустимая проблема).

Два: сделать конструктор защищенным, а затем получить к нему доступ через производный класс:

public class Bob
{
    public String Surname { get; set; }

    protected Bob()
    { }

    public Bob(string surname)
    {
        Surname = surname;
    }
}

public class Fred : Bob
{
    public Fred()
        : base()
    {
    }
}

Три : использовать отражение (как показано jgauffin).

0 голосов
/ 22 января 2017

Если вы используете ядро ​​dotnet, вы можете сделать следующее, даже не пытаясь поиграть с отражением:

YourCustomObject player = (YourCustomObject)Activator.CreateInstance(typeof(YourCustomObject),true);
0 голосов
/ 04 апреля 2014
public class demo
{
   private demo()
    {
        Console.WriteLine("This is no parameter private constructor");
    }
    public demo(int a)
    {
        demo d = new demo('c');// u can call both private contstructors from here
        demo dd = new demo();
        Console.WriteLine("This is one parameter public constructor");
    }
    private demo(char a)
    {
        Console.WriteLine("This is one parameter public constructor::" + a);
    }
}

class Program
{
    static void Main(string[] args)
    {
        demo obj = new demo(7);
        // demo obj = new demo();  // it will raise error
        Console.ReadLine();
    }
}
0 голосов
/ 12 ноября 2010

Вы можете создавать экземпляры этого типа с помощью отражения.

0 голосов
/ 12 ноября 2010

Метод Бобби все еще находится в другом классе, который называется Фред.Вот почему вы не можете получить доступ к конструктору prive класса Bob.То, что вы пытаетесь сделать, невозможно с помощью прикрепленных методов.Даже если они могут быть присоединены к другому классу, они все равно объявлены вне этого класса и следуют обычным правилам области видимости / доступа.

...