Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#使用泛型进行向下转换_C#_.net_Wpf_Generics_Casting - Fatal编程技术网

C#使用泛型进行向下转换

C#使用泛型进行向下转换,c#,.net,wpf,generics,casting,C#,.net,Wpf,Generics,Casting,在我们的项目中,我们将.NETWPF与MEF和prism一起使用。 我必须完成一些任务,作为其中的一部分,我有不同的模型类,所有这些类都实现了IModel接口(让我们称它们为Model1、Model2、Model3)。 对于每个模型类,我需要创建一个视图模型(ViewModel1、ViewModel2、ViewModel3)。 我想以某种通用的方式来实现它,这样它将是可扩展的,如果明天有人将在我不知道的不同dll中实现IModel,我仍然能够为它创建一个视图模型 我想是这样的: [Inh

在我们的项目中,我们将.NETWPF与MEF和prism一起使用。 我必须完成一些任务,作为其中的一部分,我有不同的模型类,所有这些类都实现了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>>();
    }
}
[InheritedExport]
公共接口IViewModelFactory
{
IViewModel创建(字符串id,IEnumerable modelsList);
}
公共类ViewModelFactory:IViewModelFactory
{
公共IViewModel创建(字符串id,IEnumerable modelsList)
{
返回新的ViewModel1(targetId,modelsList);;
}
}
公共类FactoryLocator
{
公共静态IViewModelFactory GetFactory(T参数)
{
返回ServiceLocator.Current.GetInstance();
}
}
然后我会这样使用它:

        public void CreateAndAddVM(IList<IModel> modelsList)
    {
        var factory = FactoryLocator.GetFactory(modelsList.FirstOrDefault());
        var vm = factory.Create(_id, modelsList);
        ViewModels.Add(vm);
    }
public void CreateAndAddVM(IList modelsList)
{
var factory=FactoryLocator.GetFactory(modelsList.FirstOrDefault());
var vm=factory.Create(_id,modelsList);
ViewModels.Add(vm);
}
当我访问FactoryLocator时,类型实际上是IModel接口,而不是Model1/2/3


有没有办法让它发挥作用?或者是实现此需求的另一种方法?

您应该从定义如下的接口开始

public interface IViewModelFactory<T> where T : IModel 
{
    IViewModel Create(string id, IEnumerable<T> modelsList);
}
公共接口IViewModelFactory,其中T:IModel
{
IViewModel创建(字符串id,IEnumerable modelsList);
}

而且它实际上会强制未来的实现者正确地输入。

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

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

考虑以下几点:

public abstract class ViewModelBase<TModel> where TModel : IModel
公共抽象类ViewModelBase,其中TModel:IModel
上面的示例将允许您的ViewModel指定它所表示的模型,但前提是一个ViewModel只有一个模型,这可能并不总是如此

在这种情况下,您的
ViewModelBase
类应该有一个ID,以及TModel的模型属性


确保
IModel
继承自
INotifyPropertyChanged
,这将允许
TModel
成为
observeCollection

类型参数在编译时得到解决,并且在编译时您的模型属于IModel类型,这正是此时出现问题的原因,任何人都可以使用可能不适用的模型创建视图模型。例如,如果您的ViewModel依赖于Model1,那么没有什么可以阻止我向工厂中的
Create
方法提供Model2列表。这可能是个问题吗?@MikeEason是的,现在我明白了。也许你可以建议另一种方法以可扩展和通用的方式解决它?@RuneFS也许你可以建议另一种方法以可扩展和通用的方式解决它?很好的建议,但它没有帮助-正如我在问题中所写,FactoryLocator中的类型仍然是IModel