通用接口

时间:2012-02-02 09:31:04

标签: c# generics interface generic-collections

我正在设计一个应用程序,其中类似的实体位于两个地方,具有不同类型的集合,如下所示。

型号:

class PersonModel {
  public string Name { get;set;}
  public List<Address> Addresses { get;}
  public List<OtherType> OtherTypes { get;}
}

类似的视图模型:

class PersonViewModel {
   public string Name { get;set;}
   public ObservableCollection<Address> Addresses { get; }
   public ObservableCollection<OtherType> OtherTypes { get; }
}

为了使两个实体保持一致,我认为使用通用接口可以确保实现所有属性,所以我创建了这样的东西:

public interface IPerson<T> where T: ICollection<T> {
   string Name { get;set;}
   T<Address> Addresses { get;}
   T<OtherType> OtherTypes [ get; } 
}

和课程将

class PersonModel<List> {}
class personViewModel<ObservableCollection> {}

但编译器还没准备好编译我的接口。 :( 说,类型参数“T”不能与类型参数一起使用。

为什么我想要这个,我想最小化从/到模型和类型的类型转换视图模型。

我的viewModel将是这样的,

class PersonViewModel<T> : IPerson<T> {
   public PersonViewModel(IPerson model){
      this.Model = model;
   }
   internal PersonModel Entity {
      get; set;
   }
   public string Name { 
      get{ return model.Name;} 
      set {model.Name = value;}
   }
   public T<Address> Addresses {
      get { return model.Addresses.Cast<T>(); }
   }
}

建议我更好地使用Model&amp; amp; ViewModel已同步。

4 个答案:

答案 0 :(得分:1)

ViewModel的存在是为View提供数据。这意味着它应该根据View的要求建模。通常,这些要求与模型的要求不同。这意味着,通常情况下,您的模型和ViewModel不会同步,它们会有所不同。在您的方法中,ViewModel不会添加任何值,可以删除。

要在ViewModel和模型之间进行映射,您可以使用AutoMapper

答案 1 :(得分:1)

您的实施应如下所示:

class PersonModel : IPerson<List> {}
class PersonViewModel : IPerson<ObservableCollection> {}

你真的需要一个通用课吗? ObservableCollection<T>List<T>都实施ICollection<T>,因此您可以在界面中分别将地址和其他类型声明为ICollection<Address>ICollection<OtherType>

(什么是AddressView?)

答案 2 :(得分:0)

你不能以这种方式使用泛型。你可以试试这样的东西

public interface IPerson
{
    string Name { get; set; }
    ICollection<Address> Addresses { get; }
    ICollection<OtherType> OtherTypes { get; }
}

public class OtherType { }
public class Address { }

然后

class PersonModel : IPerson
{
    public PersonModel()
    {
        Addresses = new List<Address>();
        OtherTypes = new List<OtherType>();
    }

    public string Name { get; set; }
    public ICollection<Address> Addresses { get; private set; }
    public ICollection<OtherType> OtherTypes { get; private set; }
}

class PersonViewModel : IPerson
{
    public PersonViewModel()
    {
        Addresses = new ObservableCollection<Address>();
        OtherTypes = new ObservableCollection<OtherType>();
    }

    public string Name { get; set; }
    public ICollection<Address> Addresses { get; private set; }
    public ICollection<OtherType> OtherTypes { get; private set; }
}

答案 3 :(得分:0)

您对IPerson的通用约束强制要求T必须实现ICollection的T?这是无休止的递归,这是不允许的。

您也无法在泛型类型上指定泛型参数,因此不允许T<Address>,这是因为不知道T是否是泛型类型。

您可以将界面更改为以下内容:

public interface IPerson<TAddressCol, TOtherCol> 
   where TAddressCol: ICollection<Address>
   where TOtherCol : ICollection<OtherType> 
{
   string Name { get;set;}
   TAddressCol Addresses { get;}
   TAddressCol OtherTypes [ get; } 
}

然后像这样使用它:

class PersonModel<List<Address>, List<OtherType>> {}
class personViewModel<ObservableCollection<Address>, ObservableCollection<OtherType>> {}

我认为这是获得所需方法的唯一真正方法。但我建议你的界面只返回ICollection<Address>ICollection<OtherType>。然后,您的model / viewmodel必须通过接口公开集合,但是没有什么能阻止您将支持实现分别设置为ListObservableCollection

相关问题