【发布时间】:2013-08-27 13:10:03
【问题描述】:
与C# - Is there a better alternative than this to 'switch on type'?相关
我需要“开启类型”:给定一个T 类型的参数,查找并执行void Method (T param) 形式的方法。
这可以通过 switch 语句或Dictionary<Type, Action> 来解决,但是我想避免在这种情况下进行必要的强制转换。
我找不到上述(或类似)问题中提到的以下方法:
-
创建一个充当集合的静态泛型类型:
public static class Commands<T> { public static Action<T> Handler; } -
创建一个像类型安全字典一样使用该类型的存储库:
public class CommandRepository { public void Register<T>(Action<T> handler) { Commands<T>.Handler = handler; } public void Run<T>(T parameter) { // null checks etc. Commands<T>.Handler(parameter); } } -
示例用法:
public void CreateUser(CreateUserParams p) { Console.WriteLine("Creating " + p.Name); } // ... var repo = new CommandRepository(); repo.Register<CreateUserParams>(CreateUser); repo.Register<DeleteUserParams>(DeleteUser); repo.Run(new CreateUserParams { Name = "test" }); repo.Run(new DeleteUserParams { Name = "test" });
如前所述,可以使用ComandRepository 中的Dictionary<Type, Action> 实现相同的行为,但是我必须转换方法参数,或者,如果我使用接口而不是Action,则转换为IFoo<T> 获取字典项后。
我的问题是:可以(ab-)使用这样的泛型类型吗(考虑到T 的大量可能值)?
(额外问题)如果不行,为什么不呢?这会导致什么成本/负面影响?
最后一点:我意识到这不适用于类型层次结构或接口。 T 类型必须完全匹配,这在我的场景中很好。
编辑:我发现Jil,一个 JSON 序列化器,也依赖于这种模式。请参阅TypeCache 类型,它存储一个委托以序列化T 类型的对象(据我通过浏览代码了解到)。由于这个TypeCache 将存储大量类型,我认为该模式通常没有问题。
了解类型或其静态成员是否需要被垃圾收集,或者是否需要考虑其他性能影响仍然很有趣。
【问题讨论】:
-
这不是我们应该使用泛型的方式吗?他们被要求做那样的事情,对吗?
-
“通用”表示相同代码用于满足约束的所有类型。如果你想为不同的类型使用不同的代码,泛型很可能是错误的工具。
-
你的所有类型都是原始的吗?如果是,请查看我的回答 here
-
这正是我工作中的几个系统的工作方式。我看不出它是如何“滥用”的,这对我来说似乎是使用泛型的好方法。对我们来说,它用于处理命令的域模型。每个命令显然需要不同的处理,因此我们将处理程序方法注册到命令类型。
-
@Dennisch 我认为这可能是滥用的原因是我最终会创建大量的泛型类型(
Commands<T>),我不确定这是否会造成任何麻烦。 (编辑)我打算以与您描述的方式类似的方式使用此模式。很高兴知道其他人正在这样做。
标签: c# generics pattern-matching