到目前为止,我的猜测是动态类型只是在编译期间“关闭”类型检查,并在动态实例上调用消息时执行类似于类型转换的操作。显然还有其他事情发生了。
附带的NUnit测试用例显示了我的问题:使用动态类型,我只能使用具体子类中可用的方法,但是我不能使用强制转换(导致InvalidCastException)。我宁愿进行强制转换,因为这样可以让我在VS中获得完整的代码完成。
有人能解释一下发生了什么和/或给我一个提示,如何在不必在每个具体子类中重新实现WorkWithAndCreate方法的情况下获得代码完成吗?
谢谢,Johannes
using System;
using NUnit.Framework;
namespace SlidesCode.TestDataBuilder
{
[TestFixture]
public class MyTest
{
[Test]
public void DynamicWorks()
{
string aString = CreateDynamic(obj => obj.OnlyInConcreteClass());
Assert.AreEqual("a string", aString);
}
private static string CreateDynamic(Action<dynamic> action)
{
return new MyConcreteClass().WorkWithAndCreate(action);
}
[Test]
public void CastingDoesNotWorkButThrowsInvalidCastException()
{
string aString = CreateWithCast(obj => obj.OnlyInConcreteClass());
Assert.AreEqual("a string", aString);
}
private static string CreateWithCast(Action<MyConcreteClass> action)
{
return new MyConcreteClass().WorkWithAndCreate((Action<MyGenericClass<string>>) action);
}
}
internal abstract class MyGenericClass<T>
{
public abstract T Create();
public T WorkWithAndCreate(Action<MyGenericClass<T>> action)
{
action(this);
return this.Create();
}
}
internal class MyConcreteClass : MyGenericClass<string>
{
public override string Create()
{
return "a string";
}
public void OnlyInConcreteClass()
{
}
}
}
以下是我评论中格式化的实际例子:
这里是一个实际例子:
Customer customer = ACustomer(cust =>
{
cust.With(new Id(54321));
cust.With(AnAddress(addr => addr.WithZipCode(22222)));
});
private static Address AnAddress(Action<AddressBuilder> buildingAction)
{
return new AddressBuilder().BuildFrom(buildingAction);
}
private static Customer ACustomer(Action<CustomerBuilder> buildingAction)
{
return new CustomerBuilder().BuildFrom(buildingAction);
}
一些细节缺失,但我希望它能清楚地表达目的。