这需要大量的麻烦,但我处理好了。
使用TypeSwitch代码让我可以对类型进行一些切换,我最初写了以下代码:
public Mapping<Address, DatabaseAddress> DatabaseAddress { get; }
public Mapping<T1, T2> GetMapping<T1, T2>()
{
Mapping<T1, T2> retMapping = null;
TypeSwitch.Do(
typeof (T1),
TypeSwitch.Case<Address>(() =>
TypeSwitch.Do(
typeof (T2),
TypeSwitch.Case<DatabaseAddress>(() => retMapping = AddressToDatabaseAddressMapping)
));
return returnedMapping;
}
retMapping = AddressToDatabaseAddressMapping
导致编译器错误,因为您无法自动分配 Mapping<Address,DatabaseAddress>
给Mapping<T1,T2>
. 即使,启发式地,它们在这里是同一件事,但它们在逻辑上并不是同一件事。
object
事实证明,您可以通过利用类型有效地使 C# 作为动态语言运行。
public Mapping<Address, DatabaseAddress> DatabaseAddress { get; }
public Mapping<T1, T2> GetMapping<T1, T2>()
{
object retMapping = null;
TypeSwitch.Do(
typeof (T1),
TypeSwitch.Case<Address>(() =>
TypeSwitch.Do(
typeof (T2),
TypeSwitch.Case<DatabaseAddress>(() => retMapping = AddressToDatabaseAddress),
));
var returnedMapping = (Mapping<T1, T2>) retMapping;
return returnedMapping;
}
这比表明我的观点所需要的要冗长一些,但有趣的是,在运行时,AddressToDatabaseAddress
即使它的静态类型并不意味着它需要它,它也会保持它的身份。而且,由于启发式地Mapping<T1, T2>
是 IS Mapping<Address, DatabaseAddress>
,它将在运行时正确地分配自己并完美地工作。
重要的是要注意,我必须添加一些东西TypeSwitch
才能typeof(T1)
正常typeof(T2)
工作。默认的写法,object source
也就是传入的是System.Type
,这不是你想要的行为!但是,添加以下重载:
public static void Do(Type source, params CaseInfo[] cases)
{
foreach (var entry in cases.Where(entry => entry.IsDefault || entry.Target.IsAssignableFrom(source)))
{
entry.Action(source);
break;
}
}
将使其按预期运行。由于System.Type
重载比重载更具体System.Object
,框架会更喜欢使用它。如果有人TypeSwitch
更喜欢直接输入类型,那么对于一个常见的用例来说会更加理智。