【问题标题】:C# Downcasting with generics使用泛型进行 C# 向下转型
【发布时间】:2015-03-15 17:29:29
【问题描述】:

在我们的项目中,我们使用带有 MEF 和 prism 的 .net WPF。 我必须做一些任务,作为其中的一部分,我有不同的模型类,它们都实现了 IModel 接口(我们称它们为 Model1、Model2、Model3)。 对于每个模型类,我需要创建一个视图模型(ViewModel1、ViewModel2、ViewModel3)。 我想用一些通用的方式来做,所以它是可扩展的,如果明天有人会在我不知道的不同 dll 中实现 IModel,我仍然可以为它创建一个视图模型。

我想是这样的:

    [InheritedExport]
public interface IViewModelFactory<T>
{
    IViewModel Create(string id, IEnumerable<IModel> modelsList);
}

public class ViewModelFactory : IViewModelFactory<Model1>
{
    public IViewModel Create(string id, IEnumerable<IModel> modelsList)
    {
        return new ViewModel1(targetId, modelsList);;
    }
}

public class FactoryLocator
{
    public static IViewModelFactory<T> GetFactory<T>(T parameters)
    {
        return ServiceLocator.Current.GetInstance<IViewModelFactory<T>>();
    }
}

然后我会这样使用它:

        public void CreateAndAddVM(IList<IModel> modelsList)
    {
        var factory = FactoryLocator.GetFactory(modelsList.FirstOrDefault());
        var vm = factory.Create(_id, modelsList);
        ViewModels.Add(vm);
    }

当我到达 FactoryLocator 时,类型实际上是 IModel 接口,而不是 Model1/2/3。

有没有办法让它以某种方式工作?或者也许是另一种实现此要求的方式?

【问题讨论】:

  • 类型参数在编译时解析,并且在编译时您的模型是 IModel 类型,这就是导致问题的原因
  • 此时,任何人都可以使用可能不适合它的模型创建视图模型。例如,如果您的 ViewModel 依赖于 Model1,则没有什么能阻止我向您工厂中的 Create 方法提供 Model2 列表。这会是个问题吗?
  • @MikeEason 是的,现在我明白了。也许您可以提出另一种以可扩展和通用的方式解决它的方法?
  • @RuneFS 也许您可以提出另一种以可扩展和通用的方式解决它的方法?

标签: c# .net wpf generics casting


【解决方案1】:

你应该从这样定义的接口开始

public interface IViewModelFactory<T> where T : IModel 
{
    IViewModel Create(string id, IEnumerable<T> modelsList);
}

它实际上会强制未来的实施者正确输入。

【讨论】:

  • 不错的建议,但没有帮助 - 正如我在问题中所写的,FactoryLocator 中的类型仍然是 IModel
【解决方案2】:

正如我在评论中提到的。此时,任何人都可以使用可能不适合它的模型创建视图模型。

例如,如果您的 ViewModel 依赖于 Model1,没有什么能阻止我向您工厂中的 Create 方法提供 Model2 的列表。

考虑以下几点:

public abstract class ViewModelBase<TModel> where TModel : IModel

上面的示例将允许您的 ViewModel 指定它所代表的模型,但是这是假设 ViewModel 只有一个模型,但情况可能并非总是如此。

在这种情况下,您的 ViewModelBase 类应该有一个 ID 和一个用于 TModel 的 Model 属性。

确保 IModel 继承自 INotifyPropertyChanged这将允许 TModel 成为一个 ObservableCollection.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    相关资源
    最近更新 更多