2011-09-12 79 views
1

我有一個關於如何使用泛型和擴展方法編譯器推斷類型的問題。最簡單的方法來問我的問題是先顯示一些代碼...泛型和擴展方法 - IntelliSense如何推斷類型?

我有一個ViewModelBase類看起來有點像這樣(與所有不相關的東西都取出)。基本上我的NavigationService類在每次應用程序轉到與之鏈接的視圖時調用NavigatingTo方法。

該類的繼承者可以調用返回委託將數據傳回給調用者。

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

    public abstract void NavigatingTo(TContext context); 
} 

然後,我有一個測試視圖模型繼承ViewModelBase:

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

接下來我有一個接受ViewModelBase這樣的通用NavigationCommand類:

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

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

而且最後我有一個NavigationCommand類的擴展方法向其添加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的I類做到以下幾點:

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實際上提示我使用正確的類型?

目前所有的智能感知帶給我的是:

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

當我想是這樣的:

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

回答

1

一個解決這個問題的方法之一是傳播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。

+0

謝謝安德魯。我真的很想避免必須明確地定義NavigationCommand中的類型,因爲如你所說它是冗長的,但是如果上下文或返回類型改變,它又是一個你必須改變的地方。關於爲什麼Intellisense不接受這個問題的任何想法? –

+0

我認爲,下面的帖子描述了原因:[http://stackoverflow.com/questions/7171067/no-type-in​​ference-with-generic-extension-method/7171527#7171527](http://stackoverflow.com/questions/7171067/no-type-in​​ference-with-generic-extension-method/7171527) –

+0

再次感謝Andrew。在發佈這個問題之前,我實際上已經閱讀過這篇文章和博客,但感覺我的情況稍有不同。在博客中,Eric似乎在討論爲什麼編譯器無法在某些情況下推斷類型,並因此引發編譯時錯誤。在我的情況下,編譯器正確地標識了類型,並且不允許使用與視圖模型中定義的類型不兼容的類型的變量。問題是智能感知不能提取它。謝謝你的時間。我想我會改變我的方法,並留下它。 –