我在一些项目的过程中开发了一种用于创建不可变(只读)对象和不可变对象图的模式.不可变对象具有100%线程安全的优点,因此可以跨线程重用.在我的工作中,我经常在Web应用程序中使用此模式来配置设置以及我在内存中加载和缓存的其他对象.缓存对象应始终是不可变的,因为您希望保证它们不会意外更改.
现在,您可以轻松地设计不可变对象,如下例所示:
public class SampleElement
{
private Guid id;
private string name;
public SampleElement(Guid id, string name)
{
this.id = id;
this.name = name;
}
public Guid Id
{
get { return id; }
}
public string Name
{
get { return name; }
}
}
Run Code Online (Sandbox Code Playgroud)
这对于简单的类来说很好 - 但是对于更复杂的类,我不喜欢通过构造函数传递所有值的概念.在属性上设置setter是更理想的,构建新对象的代码更容易阅读.
那么如何使用setter创建不可变对象?
好吧,在我的模式中,对象开始是完全可变的,直到你用一个方法调用冻结它们.一旦一个对象被冻结,它将永远保持不变 - 它不能再次变成一个可变对象.如果您需要对象的可变版本,则只需克隆它即可.
好的,现在谈谈一些代码.我在下面的代码片段中试图将模式简化为最简单的形式.IElement是所有不可变对象必须最终实现的基接口.
public interface IElement : ICloneable
{
bool IsReadOnly { get; }
void MakeReadOnly();
}
Run Code Online (Sandbox Code Playgroud)
Element类是IElement接口的默认实现:
public abstract class Element : IElement
{
private bool immutable;
public …Run Code Online (Sandbox Code Playgroud) 是否有任何方法(利用我希望的反射),我可以使实例化对象与其所有公共属性一起不可变?我有一个来自别人的代码库(没有可用的源代码)的类,我需要利用它,如果任何代码片段在实例化之后尝试调用此类中的公共setter,我基本上都希望抛出异常.
注意:我不想在类周围创建一个包装器对象来实现它.我很懒.