繁体   English   中英

泛型和扩展方法-IntelliSense如何推断类型?

[英]Generics and Extension Methods - how does IntelliSense infer types?

我有一个关于编译器在使用泛型和扩展方法时如何推断类型的问题。 问我问题的最简单方法是先显示一些代码...

我有一个看起来像这样的ViewModelBase类(删除了所有不相关的内容)。 基本上,每次应用程序进入与其链接的View时,我的NavigationService类都会调用NavigatingTo方法。

此类的继承者可以调用Return委托,以将数据传递回调用者。

public abstract class ViewModelBase<TContext, TReturn>
{
    public Action<TReturn> Return { get; set; }

    public abstract void NavigatingTo(TContext context);
}

然后,我有一个继承ViewModelBase的测试ViewModel:

public class TestViewModel : ViewModelBase<int, bool>
{
    public override void NavigatingTo(int context)
    {
        // do stuff here
    }
}

接下来,我有一个通用的NavigationCommand类,它接受如下所示的ViewModelBase:

public class NavigationCommand<TViewModel>
{
    public TViewModel ViewModel { get; set; }

    public NavigationCommand(TViewModel viewModel)
    {
        this.ViewModel = viewModel;
    }
}

最后,我有一个NavigationCommand类的扩展方法,可以向其添加Navigate方法。 我的目的是通过声明我的Navigate方法需要一个带有TContext和TReturn的ViewModelBase,编译器应该能够推断出实际使用的类型:

public static class NavigationExtensions
{
    // I actually pass in a INavigationService here too, but I have left that out to
    // make it easier to read...

    public static void Navigate<TViewModel, TContext, TReturn>(
        this NavigationCommand2<TViewModel> viewModel, 
        TContext context, 
        Action<TReturn> returnAction) 
        where TViewModel : ViewModelBase<TContext, TReturn>
    {
        // actual implementation omitted
    }
}

好的,现在在我的ApplicationController类中,执行以下操作:

var vm = new TestViewModel();
var cmd = new NavigationCommand2<TestViewModel>(vm);

int clientID = 1;

Action<bool> returnAction = success =>
{
    Console.WriteLine(success.ToString());
};

cmd.Navigate(clientID, returnAction);

它可以正常工作,并且如果您尝试传递不正确的类型,则在生成时会出现编译器错误。 但是,Intellisense不会提示您输入正确的类型。

所以我的问题是:有什么方法可以重写扩展方法,我的NavigationCommand类或ViewModel等,以便Intellisense实际提示我使用正确的类型?

目前,Intellisense给我的一切是这样的:

(extension void) NavigateCommand<TestViewModel>.Navigate(TContext context, Action<TReturn> returnAction)

当我想要的是:

(extension void) NavigateCommand<TestViewModel>.Navigate(int context, Action<bool> returnAction)

解决此问题的方法之一是将TContext和TReturn类型参数传播到NavigationCommand,因此其声明如下所示:

public class NavigationCommand<TViewModel, TContext, TReturn> where TViewModel:ViewModelBase<TContext, TReturn>

但这会使命令初始化更加冗长(因为TestViewModel类型实际上已经包含有关TContextTReturn实际类型的信息):

var cmd = new NavigationCommand<TestViewModel, int, bool>(vm);

实际上,您发布的实现已经是类型安全的,并且不允许您传递错误类型的参数(比如说用string代替int )。 唯一的问题是Intellisense,由于某种原因,它无法正确推断类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM