问题描述
|
这个有点奇怪...
可以说我有以下课程:
public class Wibble
{
public string Foo {get;set;}
public string Bar {get;set;}
}
此类用于更新/更改Foo和Bar的值的过程。但是,在过程中的某个步骤之后,我想“锁定”实例以防止进行任何更改。那么问题是如何最好地做到这一点?
各种各样的解决方案是这样的:
public class Wibble
{
private string _foo;
private string _bar;
public bool Locked {get; set;}
public string Foo
{
get
{
return this._foo
}
set
{
if (this.Locked)
{
throw new ObjectIsLockedException()
}
this._foo = value;
}
}
public string Bar
{
get
{
return this._bar
}
set
{
if (this.Locked)
{
throw new ObjectIsLockedException()
}
this._bar = value;
}
}
}
但是,这似乎有点不雅致。
想要这样做的原因是,我有一个应用程序框架,该框架使用使用该类的外部开发的插件。 Wibble类被传递到插件中,但是其中一些插件永远都不能更改其内容,其中一些插件可以更改。其背后的目的是抓住开发集成问题,而不是运行时生产问题。使用对象“锁定”允许快速识别未按指定编码的插件。
解决方法
我已经实现了与锁定模式相似的功能,但是还实现了一个只读接口,该接口由包含实际类数据的私有子类实现,因此您可以清楚地看到数据的只读视图并且无法向上转换到原始的“可变版本”。锁定纯粹是为了防止数据提供者在提供不变的视图之后进行进一步的更改。
正如您所指出的那样,它工作得还算不错,但是有点尴尬。我认为拥有可变的“ Builder”对象实际上可以更清洁,然后可以生成不可变的快照。想想StringBuilder和String。这意味着您需要复制一些属性代码,并且必须编写例程来进行复制,但是在我看来,它比在每个属性上都具有写锁更为尴尬。在编译时也很明显,快照应该是只读的,并且Builder的用户无法修改其先前创建的快照。
,我建议这样做:
一个不变的基类:
public class Wibble
{
public string Foo { get; private set; }
public string Bar { get; private set; }
public Wibble(string foo,string bar)
{
this.Foo = foo;
this.Bar = bar
}
}
然后,您可以更改一个可变的类,然后在时间到来时创建一个不变的副本。
public class MutableWibble
{
public string Foo { get; set; }
public string Bar { get; set; }
public Wibble CreateImmutableWibble()
{
return new Wibble(this.Foo,this.Bar);
}
}
我不记得确切的C#语法,但是您明白了。
进一步阅读:http://msdn.microsoft.com/en-us/library/acdd6hb7%28v=vs.71%29.aspx
,您不能使对象不变!
您可以关注这篇文章:
如何创建一个不变的类?
但是我认为您总是可以通过反射来更改属性值!
更新
\“ ...实际上,字符串对象不是那个
据我所知,至少有两种方法可以打破字符串
不变性。使用此代码示例所示的指针以及一些高级System.Reflection用法。...\“
http://codebetter.com/patricksmacchia/2008/01/13/immutable-types-understand-them-and-use-them/
,您拥有的另一个选项是使用BinaryFormatter创建要被“锁定”的对象的成员克隆。尽管您没有锁定对象,但是您正在创建快照,在原始快照保持不变的情况下可以将其丢弃。