用于双通用函数的语法糖

时间:2011-10-04 07:23:25

标签: c# generics syntax

我在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>();

还有其他可能吗?我的解决方案是否完全错误了?

2 个答案:

答案 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();