Доступ к частному конструктору из класса вне класса С#
Если я определяю класс с частным конструктором по умолчанию и публичным конструктором с параметрами, как я могу получить доступ к частному конструктору?
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 прямо сейчас, поэтому моя идея может быть или не быть "неправильным способом" для выполнения вещей.
Я изменил свою стратегию тестирования, чтобы просто сделать так, как потребитель этого класса будет, то есть вызвать общедоступные методы, и если общедоступные методы будут в порядке, предполагая, что частные методы в порядке. Я бы предпочел испытать частные методы, но мой босс дышит мне на шею: - (
Ответы
Ответ 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();
}
}