我有各种派生对象,我希望用户能够使用对象初始化器。我有一个“初始化”属性,我希望在设置这些字段时为true,然后我希望之后将Initializing属性设置为false。
如何判断对象初始化程序何时能够执行此操作?
class Foo
{
Public Foo(string p1, string p2)
{
Initializing = true;
Property1 = p1;
Property2 = p2;
Initializing = false;
}
bool Initializing;
string _property1;
string Property1
{
get { return _property1; }
set { _property1 = value; DoSomething(); }
}
string Property2 { get; set; }
public void DoSomething()
{
if(Initializing) return; // Don't want to continue if initializing
// Do something here
}
}
在上面的示例中,如果使用构造函数,它可以正常工作。但是如何使用对象初始化器以相同的方式工作是一个问题。
编辑:对于你所有的反对者,这里有其他人正在寻找我正在追求的东西 - http://blogs.clariusconsulting.net/kzu/how-to-make-object-initializers-more-useful/
不幸的是,它确实看起来像是不可能的。
答案 0 :(得分:4)
如果您确实需要跟踪对象的初始化,那么您需要手动实现该逻辑。一种方法是复制WinForms代码生成器使用的方法。对象在希望批量更新属性时公开ISupportInitialize接口的位置。所以用法就像......
var x = new Foo();
x.BeginInit();
x.Property1 = 1;
x.Property2 = 2;
x.EndInit();
答案 1 :(得分:3)
设置任何标志都没有意义。在初始化程序运行之前,您无法访问对象。例如:
var object = new object() { Prop1 = "Boo" }
由于在设置Prop1之后无法访问从new返回的引用,因此无法访问任何属性,因此无需控制访问权限或担心它是否“完成”。
虽然,我想我可以看到你可能会有这样的事情:
public class Foo {
private int _value;
public int Bar {
set {
_value = value * Baz; // don't want to do this if initializing
}
}
public int Baz { get; set; }
}
如果这是您所关注的问题,那么您就错误地设计了对象。属性不应该像这样的副作用。没有办法知道是否所有的初始化都已完成。
答案 2 :(得分:1)
这个问题毫无意义。对象初始化器语法只是语法糖的简写。
此:
var myInstance = new someClass()
{
Prop1 = "",
Prop2 = "",
Prop3 = "",
Prop4 = "",
Prop5 = ""
}
与此完全相同:
var myInstance = new someClass();
myInstance.Prop1 = "";
myInstance.Prop2 = "";
myInstance.Prop3 = "";
myInstance.Prop4 = "";
myInstance.Prop5 = "";
无法检测到“完成”。
你想做什么我们可以做的事情:
class someClass()
{
public string AStringProperty { get; set; }
public bool IsInitiazlied
{
return string.IsNullOrWhitespace(this.AStringProperty);
}
}
或者,让ctor取值的初始状态,然后保证你的设置。
class someClass()
{
public string AStringProperty { get; set; }
public someClass(string AStringPropertyInit)
{
this.AStringProperty = AStringPropertyInit;
}
}
修改强> 的
class Foo
{
Public Foo(string p1, string p2)
{
_property1= p1; //set the backing store directly,
//skips the side effect in the setter
Property2 = p2;
DoSomething(); // now cause the side effect
// we know everything is setup
}
string _property1;
string Property1
{
get { return _property1; }
set { _property1 = value; DoSomething(); }
}
string Property2 { get; set; }
public void DoSomething()
{
// Do something here
}
}
答案 3 :(得分:1)
由于对象初始化只是语法糖,因此无法区分它和普通属性集。我也不能想到一个合理的案例,你想以不同的方式对待它们。
也就是说,如果你说必须设置至少1个x属性(无论是简写还是简写语法),那么你可以在ctor中设置初始化为true,然后在每个属性集上将其设置为false。
答案 4 :(得分:1)
您可以让DoSomething
方法验证它是否具有完成工作所需的信息,而不是依赖于显式属性来告诉您对象何时初始化。你的例子很粗糙,我希望你的实际实现更复杂,所以我只假设必须将Property1
和Property2
分配给某些东西(意思就是不是继续前空字符串):
class Foo
{
public Foo(string p1, string p2)
{
Property1 = p1;
Property2 = p2;
}
string Property1 { get; set; }
string Property2 { get; set; }
public void DoSomething()
{
// *** Replace this with something valid to your real code
if(!string.IsNullOrEmpty(Property1) || !string.IsNullOrEmpty(Property2))
return; // Don't want to continue if not initialized
// Do something here
}
}
<强>更新强>
不了解您实际使用的对象模型,这里有一个基于整个框架中广泛使用的模型的可能替代方案:
class Foo
{
public void DoSomething(FooConfig config)
{
}
}
或强>
class Foo
{
private FooConfig config_;
public Foo(FooConfig config)
{
config_ = config;
}
public void DoSomething()
{
}
}
定义FooConfig
的位置:
class FooConfig
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
使用以下方式调用DoSomething
:
(new Foo()).DoSomething(new FooConfig() { Property1 = "abc"; Property2 = "def"; });
OR
(new Foo(new FooConfig() { Property1 = "abc"; Property2 = "def"; })).DoSomething();
可以轻松更改此设置,以适应Foo
或FooConfig
上的构造函数使用情况。
答案 5 :(得分:0)
对象初始化器只是创建对象和在其上设置一组属性的简写。问“何时完成”并不合理。
如果您希望对象的状态依赖于初始化的特定属性集,那么您可以为每个属性的setter添加代码并在内部跟踪它。但这确实取决于你想要实现的目标。
<强>更新强>
只是阅读你对@asawyer的答案的评论。没有办法判断是否在初始化程序中设置了属性。只是为了说明 - 这里有三段完全相同的代码,除了你似乎想要一个不同的行为。
var someVar1 = new SomeClass()
{
Prop1 = "value1";
Prop2 = "value2";
};
var someVar2 = new SomeClass()
{
Prop1 = "value1";
};
someVar2.Prop2 = "value2";
var someVar3 = new SomeClass();
someVar3.Prop1 = "value1";
someVar3.Prop2 = "value2";
跟踪单个属性设置器的执行情况并不难,并且除了第一次执行外,还会触发一些副作用,但是如果客户端更改初始对象配置,我只想触发副作用在ctor完成后没有任何意义。