我不知道这是否可行,但在我的一些单元测试中,我最终用相同的参数初始化不同的对象。我希望能够将这些参数存储在某个变量中,并使用该变量初始化多参数对象构造函数,而不是执行:
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#语法糖?
答案 0 :(得分:13)
我的意思是,就是这样:
Func<Thing> f = () => new Thing(arg1, arg2, arg3, arg4);
Thing thing1 = f();
Thing thing2 = f();
Thing thing3 = f();
Thing thing4 = f();
答案 1 :(得分:3)
嗯,我想你可以使用一个IoC容器,因为其中一些也提供了一个ObjectFactory,即你告诉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);
}
}
然而请记住,如果参数不是值类型,那么Thing
的所有实例都将引用相同的对象,因此,即使您有不同的事物实例,它们都会指向到同一个arg1。你可以做些什么来修复它实际上在参数中接受一个Func,所以你可以实际创建一个新的:
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();
你每次都会得到一个新的Thing实例,每个实例都有自己的属性对象。
答案 2 :(得分:1)
还有这个,假设你的Thing1是一个琐碎的对象,你只需要一个浅的副本:
Thing thing1 = new Thing(arg1, arg2, arg3, arg4);
Thing thing2 = (Thing)thing1.MemberwiseClone();
答案 3 :(得分:1)
您可以使用一些仿制药将GimmieAThing
重写为GimmieAThing<T>
之类的内容吗?
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]);
}
}
答案 4 :(得分:1)
我建议调查Test Data Builder模式。当您有许多参数可以独立变化,重复使用等时,它的效果非常好。
您可以使用properties + object initializers for 'flat' classes或流体方法链接作为替代方法。我玩弄了两者,各有其优势。
优点:
如果您需要创建每个参数的新实例,请查看bangoker的答案。
无论如何,这里有一些代码:
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();
答案 5 :(得分:1)
在方法中使用params
声明,如下所示:
public Thing(params string[] args)
{
foreach(string s in args)
{
...
}
}
它将允许您执行以下操作:
result = Things(arg1)
result = Things(arg1,arg2)
result = Things(arg1,arg2,arg3)
result = Things(arg1,arg2,arg3,arg4)
答案 6 :(得分:0)
如果你需要多次这样做,你也可以使用一个对象数组和一个for循环。