2011-06-07 130 views
1

我为我们的MVVM应用程序中编写一个弹出窗口服务。C#泛型类型解决

我已经在弹出的控制器

void ShowDialogWithResult<TView, TViewModel, TResult>(Action<TResult, WindowClosedEventArgs> callbackAction) 
      where TView : FrameworkElement, IPopupContent<TViewModel> 
      where TViewModel : IResultViewModel<TResult>; 

写了这个方法,你可以看到,以显示与视图模型一个弹出窗口,并导致该视图必须实现IPopupContent<TViewModel>接口,并反过来视图模型必须实现接口IResultViewModel<TResult>

因此,我们的类型链从TView-> TViewModel-> TResult

开始调用该方法是这样的:

_childWindowController 
       .ShowDialogWithResult<AddNationalityPopup,AddNationalityPopupModel, AddNationalityResult>(
        (result, a) => 
        { 
         if (a.DialogResult.HasValue && a.DialogResult.Value) 
         { 
          if (result.NationalityCountryId.HasValue) 
          { 
           Background.NationalityCountryId = result.NationalityCountryId.Value; 
           Background.NationalityDescription = result.NationalityDescription; 
          } 
         } 
        }); 

正如你所看到的,我强制传递所有三种类型的参数供编译器生成正确的方法。

这代码让我伤心。如何减少调用所需的类型参数数量,并仍然保持类型安全。我无法开发任何有效的解决方案。

+0

你怎么能指望它来推断'TResult'的类型? – 2011-06-07 08:40:31

+0

我有一种感觉,协变可以处理它。 另外,如果我可以说编译器将只有IPopupContent和IResultViewModel的单一实现,那么编译器可以安全地从视图中获取类型。 – v00d00 2011-06-07 08:52:10

+0

编译器无法知道会有永远只能是一个实现的接口方式。即使在你编写的代码中,并且接口被标记为“内部”,它也没有足够的分析能力来排除使用实现相同接口的Reflection.Emit来即时构建新类。 – 2011-06-07 09:07:59

回答

1

有没有在这一呼吁减少这些泛型类型参数的方式,但你可以为它专门超载这种方法使用继承。

例如,如果有很多电话是给.ShowDialogWithResult<AddNationalityPopup,AddNationalityPopupModel, ...>,你可以继承你的控制器,并添加过载像.ShowDialogWithResult<TResult>

取2:

这样的另一种方法将被添加这些方法的一般类型参数到控制器类和使用控制反转,能够与此时,相应的类型的参数释放提供他们的呼叫者实例化在.ShowDialogWithResult(...)

+0

不幸的是,我不得不有这种控制器的单一实例,但无论如何,好点。 – v00d00 2011-06-07 08:47:28

+0

为什么不使用控制反转来选择正确的控制器? – 2011-06-07 08:58:48

+0

@Dmitry检查我的更新,“采取2”。 – 2011-06-07 09:04:15