fin*_*nnw 12 c# language-agnostic design-patterns immutability builder-pattern
存在哪些工具/库将采用结构并自动生成不可变包装器以及用于逐步构建新实例的"构建器"类?
输入示例:
struct Foo
{
public int apples;
public int oranges;
public Foo Clone() {return (Foo) base.MemberwiseClone();}
}
Run Code Online (Sandbox Code Playgroud)
示例输出:
public class ImmutableFoo // could probably be a struct
{
private Foo snapshot;
internal ImmutableFoo(Foo value) { this.snapshot = value; }
public FooBuilder Builder() { return new FooBuilder(snapshot); }
public int Apples { get { return snapshot.apples; } }
public int Oranges { get { return snapshot.oranges; } }
}
public class FooBuilder
{
private Foo state;
public int Apples { get { return state.apples; } set { state.apples = value; } }
public int Oranges { get { return state.oranges; } set { state.oranges = value; } }
public FooBuilder() { }
internal FooBuilder(Foo toCopy) { state = toCopy.Clone(); }
public ImmutableFoo Build()
{
ImmutableFoo result = new ImmutableFoo(state);
state = state.Clone();
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
这样的"工具"可以是IDE插件,也可以在运行时使用反射生成新类.
这个例子是在C#中,但我会对任何静态类型的OO语言(Java,Scala,C++等)的解决方案感兴趣.
理想的功能:
Equals()
与GetHashCode()
和任何接口方法)IFooReader
包含每个struct成员的只读属性的接口,由不可变和构建器实现.List
- > ReadOnlyCollection
或类似.Clone
预定义方法"你不应该使用这样的工具,因为......"答案也是受欢迎的.
这里有四种可能的解决方案。
1) 使用CodeDOM生成C#或VB代码。这还允许您使用 Visual Studio 扩展在设计器文件中生成代码。类似于 Visual Studio 已经提供的一些内置工具 - 例如为 Web 服务调用生成包装器的工具等。不幸的是,我对扩展 Visual Studio 不太了解。
2) 使用Mono.Cecil库分析构建后的程序集。然后,您可以使用包含的新类型重新编写程序集。
3)使用PostSharp。我对这个库了解不多,因此您可能无法向程序集中添加新类型,但我知道您可以将 IL 注入到方法中。它还具有许多好东西,可以轻松地使用属性来完成此操作。所以你可以这样做 -
[GenerateImmutable]
struct Foo
{
public int apples;
public int oranges;
public Foo Clone() {return (Foo) base.MemberwiseClone();}
}
Run Code Online (Sandbox Code Playgroud)
4) 使用内置的Reflection.Emit库生成具有不可变类型的新程序集。