从状态对象导航(1
这个练习的要点是在有状态的对象之间进行导航。
例如,拥有1-1和1-1的联系人应该:
这是实现它的代码片段。
public class A {
internal B a;
public B Value {
get {
return a;
}
set {
if (value == null) {
if (a != null)
a.a = null;
} else
value.a = this;
a = value;
}
}
}
public class B {
internal A a;
public A Value {
get {
return a;
}
set {
if (value == null) {
if (a != null)
a.a = null;
} else
value.a = this;
a = value;
}
}
}
这允许以下测试通过:
// For the common setup:
var a = new A();
var b = new B();
// Test 1:
a.Value = b;
Assert.AreSame(a, b.Value);
// Test 2:
b.Value = a;
Assert.AreEqual(b, a.Value);
// Test 3:
b.Value = a;
b.Value = null;
Assert.IsNull(a.Value);
// Test 4:
var a2 = new A();
b.Value = a2;
Assert.AreSame(b, a2.Value);
Assert.AreNotSame(a, b.Value);
// Test 5:
a.Value = b;
Assert.AreSame(a, b.Value);
var a1 = new A();
var b1 = new B();
a1.Value = b1;
Assert.AreSame(a1, b1.Value);
// Test 6:
var a1 = new A();
var b1 = new B();
Assert.IsNull(a.Value);
Assert.IsNull(b.Value);
Assert.IsNull(a1.Value);
Assert.IsNull(b1.Value);
现在的问题是:如何在setter中抽象代码以避免在编写大量这样的类时可能出现的错误?
条件是:
我真的不明白你的挑战。 当你实例化类A的几个实例,然后实例化类B的单个实例时会发生什么?
A a1 = new A();
A a2 = new A();
A a3 = new A();
A a4 = new A();
A a5 = new A();
B b = new B();
哪个测试通过? 哪一个失败?
你看,一旦A
被实例化,它就有一个状态 。 这个状态应该以某种方式与一个现有实例 B
的实例有关 。 所以即使在你实例化这个A
类之前,这个B
实例也必须存在。
对于B
一个实例也是如此。 它应该引用已有的A
实例。
据我所知,A类应该有一个构造函数,引用一个现有的B实例:
public class A
{
private B b;
public A(B b)
{
this.b = b;
}
}
// Then you can have:
B b1 = new B();
A a1 = new A(b1); // here's the link
B b2 = new B();
A a2 = new A(b2); // and another link
无论是这个还是其他方式与B
你写道你不想改变A
和B
的公共签名,并且你不想将工厂添加到代码中。 在这样的限制下,我确实看不到一致的解决方案。 或者,挑战本身不够清楚?
编辑:在这里做一个疯狂的猜测,我认为你在这里实现的东西可以用反射来完成:你可能想要反映现有的代码(在调用堆栈中),并匹配一个新的实例,比如说, A
到现有的B
实例。 这可以使用反射来完成,但它非常困难,而且您必须为A
s和B
s的新实例之间的链接建立一组具体且强大的规则。 如果这是所需解决方案的方向,那么我认为你应该深入思考并看看它是如何发展的,这是一个巨大的领域。
上一篇: Abstracting from Stateful object navigation (1
下一篇: Use LINQ to get items in one List<>, that are not in another List<>