Я не знаю, возможно ли это, но в некоторых моих модульных тестах, я заканчиваю тем, что инициализировал различные объекты с теми же аргументами. Я хотел бы смочь сохранить те аргументы в некоторой переменной и просто инициализировать конструктора мультиобъекта параметра с той переменной так вместо выполнения:
Thing thing1 = new Thing(arg1, arg2, arg3, arg4);
Thing thing2 = new Thing(arg1, arg2, arg3, arg4);
Thing thing3 = new Thing(arg1, arg2, arg3, arg4);
Я мог сделать следующее:
MagicalArgumentsContainer args = (arg1, arg2, arg3, arg4);
Thing thing1 = new Thing(args);
Thing thing2 = new Thing(args);
Thing thing3 = new Thing(args);
Есть ли любой способ сделать это без переопределения Thing
конструктор для взятия списка, из которого это вручную взрывает и щипает аргументы? Возможно, немного синтаксического сахара C#?
Я имею в виду, есть это:
Func<Thing> f = () => new Thing(arg1, arg2, arg3, arg4);
Thing thing1 = f();
Thing thing2 = f();
Thing thing3 = f();
Thing thing4 = f();
просто осторожны в семантике закрытия .
Я бы предложил посмотреть в тестовый построитель данных . Он работает очень хорошо, когда у вас есть много параметров, которые вы хотите варьироваться независимо, повторно использовать и так далее.
Вы можете использовать Свойства + инициализаторы объекта для «плоских» классов или метод жидкости в качестве альтернативы. Я играл с обоими, и у каждого есть свои преимущества.
Преимущества:
Если вам нужно создать новые экземпляры каждого параметра, проверьте ответ Бангкера.
Во всяком случае, вот какой-то код:
public class ThingBuilder
{
// set up defaults so that we don't need to set them unless required
private string m_bongoName = "some name";
private DateTime m_dateTime = new DateTime(2001, 1, 1);
private int m_anotherArg = 5;
private bool m_isThisIsGettingTedious = true;
public ThingBuilder BongoName(string bongoName)
{
m_bongoName = bongoName;
return this;
}
public ThingBuilder DateTime(DateTime dateTime)
{
m_dateTime = dateTime;
return this;
}
// etc. for properties 3...N
public Thing Build()
{
return new Thing(m_bongoName, m_dateTime, m_anotherArg, m_isThisGettingTedious);
}
}
Использование (однажды экземпляр):
// notice that the parameters are now explicitly named + readable!
Thingy builtInstance = new ThingBuilder()
.BongoName("um bongo")
.DateTime(DateTime.Now)
.GettingTedious(true)
.Build();
Несколько экземпляров:
var builder = new ThingBuilder()
.BongoName("um bongo")
.DateTime(DateTime.Now)
.GettingTedious(true);
// let's make multiple objects
Thing builtThing = builder.Build();
Thing anotherBuiltThing = builder.Build();
Вы могли бы переписать Thimiting
к чему-то вроде Thimiting <11>
, используя немного универсальных?
public class MagicalArgumentsContainer
{
object[] _myParams;
public MagicalArgumentsContainer (params object[] myParams)
{
_myParams = myParams;
}
public Thing GimmieAThing()
{
return new Thing(_myParams[0], _myParams[1], _myParams[2], _myParams[3]);
}
}
Ну, я думаю, вы можете использовать контейнер IOC, поскольку несколько из этого также предлагают объектную продукцию, то есть вы сообщете IOC, как сделать новый экземпляр типа T, а затем вы просто задаете IOC, чтобы дать вам экземпляр Отказ
Однако, если вы не хотите получить IOC, вы можете сделать себя небольшим заводским классом
public MagicFactory
{
T arg1, T2 arg2, T3 arg3,.., TN argN;
public MagicFactory(T1 a1,..., TN aN)
{
this.arg1=a1;
...
this.argN = an;
}
public Thing GimmeDaThing()
{
return new Thing(this.arg1,...,this.argN);
}
}
, однако имейте в виду, что если аргументы не имеют значения значений, то все ваши экземпляры вещь
У вас будут ссылки на те же объекты, поэтому, хотя у вас есть разные случаи вещей, все они будут указывать на то же ARG1. То, что вы могли бы сделать, чтобы исправить, это фактически принимать в функции в параметре, поэтому вы действительно можете создать новый:
public MagicFactory
{
Func<T1> arg1, ,.., Func<TN> argN;
public MagicFactory(Func<T1> a1,..., Func<TN> aN)
{
this.arg1=a1;
...
this.argN = an;
}
public Thing GimmeDaThing()
{
return new Thing(this.arg1(),...,this.argN());
}
}
, и вы бы назвали так:
var magicContainer = new MagicFactory(()=> new T1(...),..., ()=>new T2(..);
var thing1 = magicContainer.GimmeDaThing();
var thing1 = magicContainer.GimmeDaThing();
var thing1 = magicContainer.GimmeDaThing();
var thing1 = magicContainer.GimmeDaThing();
, и вы получите новый экземпляр вещей Каждый раз каждый со своими собственными объектами собственности.
Если ваш класс действительно такой большой, то звучит так, будто вы должны разбивать вспомогательные объекты , а не только вспомогательные методы (хотя извлечение методов часто является шагом на этом пути). После того, как вы сделали это, ваш старый класс становится проще и проще для тестирования (возможно, с издевками, возможно, нет), и вы можете проверить методы на новых вспомогательных классов непосредственно.
Я предпочитаю проверять объект через открытый API. Если это слишком сложно, то это намек на то, что объект должен быть разбит.
-121--2596291-Это также, предполагая, что ваш Thing1 является тривиальным объектом, и вам просто нужна неглубокая копия:
Thing thing1 = new Thing(arg1, arg2, arg3, arg4);
Thing thing2 = (Thing)thing1.MemberwiseClone();
-121--3572510- Вы также можете использовать массив объектов и цикл for, если вам нужно сделать это много раз.
Также есть это, предполагая, что ваша вещь1 является тривиальным объектом, и вам просто нужна неглубокая копия:
Thing thing1 = new Thing(arg1, arg2, arg3, arg4);
Thing thing2 = (Thing)thing1.MemberwiseClone();