Подтвердить что ты не робот

Доступ к частному конструктору из класса вне класса С#

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

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

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

Спасибо


EDIT:

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

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

4b9b3361

Ответ 1

Новый ответ (девять лет спустя)

В настоящее время существует несколько перегрузок для Activator.CreateInstance, которые позволяют использовать не публичные конструкторы:

Activator.CreateInstance(typeof(YourClass), true);

true = использовать непубличные конструкторы.

.

Старый ответ

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

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

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

Edit

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

Изменить 2

Забыл обязательный флаг.

Ответ 2

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

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

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

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

    protected Bob()
    { }

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

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

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

Ответ 3

В дополнение к ответу @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.

Ответ 4

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

YourCustomObject player = (YourCustomObject)Activator.CreateInstance(typeof(YourCustomObject),true);

Активатор находится только в пространстве имен системы.

Ответ 5

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

Ответ 6

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

Ответ 7

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