如何避免指定类型参数

时间:2012-03-02 22:46:53

标签: c# generics

我有这种扩展方法:

    public static void PublishOnClient<THub, T>(this IObservable<T> observable, Expression<Func<THub, dynamic>> expression) where THub : Hub, new ()
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException("'expression' should be a member expression");
        }

        observable.Subscribe(x => Console.WriteLine(memberExpression.Member.Name));
    }

我这样使用它:

Observable.Interval(TimeSpan.FromSeconds(2))
          .PublishOnClient<TicketHub, long>(x => x.SomeValue);

但我更愿意使用它,而不是像那样指定T:

Observable.Interval(TimeSpan.FromSeconds(2))
          .PublishOnClient<TicketHub>(x => x.SomeValue);

我根本不关心T.我想要的是提供THub以一种类型安全的方式来获取成员属性的字符串。但是我希望扩展方法在IObservable上可用。我怎么能这样做?

2 个答案:

答案 0 :(得分:3)

认为你可以通过引入一种中间类型来逃避:

// All these names are bad... I don't know the domain here :)
public class Publisher<T>
{
    private readonly IObservable<T> observable;

    internal Publisher(IObservable<T> observable)
    {
        this.observable = observable;
    }

    public void OnClient<THub>(Expression<Func<THub, dynamic>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException(...);
        }

        string name = memberExpression.Member.Name;
        observable.Subscribe(x => Console.WriteLine(name));
    }
}

public static class ObservableExtensions
{
    public static Publisher<T> Publish<T>(this IObservable<T> observable)
    {
        return new Publisher<T>(observable);
    }
}

然后你可以这样称呼它:

Observable.Interval(TimeSpan.FromSeconds(2))
          .Publish().OnClient<TicketHub>(x => x.SomeValue);

Publish()方法使用T的类型推断,只留下一个类型参数来为OnClient()方法提供。

这意味着您必须进行两次方法调用而不是一次,但这是您为“部分”类型推断所付出的代价:(

答案 1 :(得分:0)

您必须明确指定所有参数,或者让所有参数由args隐式决定。 C#不支持部分参数规范。