我在c#中有以下功能:
bool Handle<TCommandHandler, TModel>(TModel model) where TCommandHandler : ICommandHandler<TModel> {
// ...
_container.Resolve<TCommandHandler>();
// ...
}
由于TModel
从函数参数中清除,我想要一些方法在调用函数时不指定其类型。理想情况下,我想称之为:
Handle<MyCommandHandler>(model);
由于这可能是不可能的,我想出了以下内容:
HandleTemp<TModel> Handle<TModel>(TModel model) {
return new HandleTemp<TModel>(model);
}
public class HandleTemp<TModel> {
private TModel _model;
public HandleTemp(TModel model) { _model = model;}
public bool With<TCommandHandler>() where TCommandHandler : ICommandHandler<TModel> {
}
}
所以我现在称之为:
Handle(model).With<MyCommandHandler>();
还有其他可能吗?我的解决方案是否完全错误了?
答案 0 :(得分:4)
不,您的分析和解决方案看起来是正确的。实际上,泛型类型推断只能在全有或全无的基础上起作用。如果存在一些无法推断的通用参数,则必须明确说明所有参数。就个人而言,我非常喜欢说“你担心这些参数,我会告诉你这个参数”,但......那是不存在的。
唯一的另一个选择是添加一个人工的额外常规参数,以允许它推断通用参数 - 有点难看。
另一个选择:挑战这里需要泛型的假设。例如,它可能只是一个Type
实例吗?将:
bool Handle<TModel>(TModel model, Type type)...
...
Handle(model, typeof(MyCommandHandler));
例如,工作?我无法直接回答这个问题,因为我不知道您的_container.Resolve<TCommandHandler>();
方法的详细信息,是否可以调整来调整Type
而不是{ <T>
。
答案 1 :(得分:1)
所有C#编译器的需求都是参数中类型的演示,因此不要试图将它放在泛型参数中(在使用站点上),而是创建一些允许您提供帮助编译器识别该类型的参数的东西。为了减少混淆,这里有一个例子:
// Your classes/interfaces.
class Container
{
public static T Resolve<T>()
{
Console.WriteLine("Resolving {0}", typeof(T).FullName);
return default(T);
}
}
interface ICommandHandler<TModel>
{
void DoSomething();
}
// An implemented ICommandHandler.
public class WackyCommandHandler : ICommandHandler<string>
{
public void DoSomething() { }
}
// Used to help the C# compiler identify types.
public static class Identify
{
public static TypeIdentity<TType> TheType<TType>()
{
return null; // You don't actually need an instance.
}
}
public sealed class TypeIdentity<TType>
{
private TypeIdentity() { }
}
// Your method
static bool Handle<TCommandHandler, TModel>(TModel model, TypeIdentity<TCommandHandler> handler)
where TCommandHandler : ICommandHandler<TModel>
{
var item = Container.Resolve<TCommandHandler>();
return true;
}
// And the usage site:
var a = "hello";
Handle(a, Identify.TheType<WackyCommandHandler>());
Console.ReadLine();