2012-02-02 145 views
1

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

型号:

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; } 
} 

and classes will将

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

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

原因,我想这一点,我想尽量减少类型转换/到&视图模型建模。

我的视图模型将会怎样对此,

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>(); } 
    } 
} 

建议我更好的办法,有型号&视图模型同步。

+0

也许你应该只使用Automapper。 – CodesInChaos 2012-02-02 09:38:42

+0

我已经使用它,但团队成员不喜欢它的大和嵌套实体 – hungryMind 2012-02-02 09:40:36

回答

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; } 
} 
+0

,但这确实确保ViewModel – hungryMind 2012-02-02 09:49:04

+0

这是否工作? C#不允许协变返回类型。 – Lukazoid 2012-02-02 09:50:18

+0

@Lukazoid,是的,我搞砸了,并纠正了代码。现在它可以工作。 – oleksii 2012-02-02 11:13:46

1

视图模型存在,为查看提供的数据,这意味着它应该是MOD在View的要求之后退出。通常情况下,这些要求与模型不同。这意味着,通常情况下,您的Model和您的ViewModel不会同步,它们会有所不同。在你的方法中,ViewModel没有添加任何值,可以删除。

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

1

你的实现应该如下所示:

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

你真的需要一个泛型类? ObservableCollection<T>List<T>都执行ICollection<T>,因此您可能能够分别在您的接口中声明地址和其他类型为ICollection<Address>ICollection<OtherType>

(什么是AddressView?)

+0

问题不是与类但接口,我的接口正在编译。更改AddressView到地址 – hungryMind 2012-02-02 09:47:35

0

您对IPerson通用的限制被执行的是T必须实现T的ICollection?这是无法递归的,这是不允许的。

您也不能在通用类型上指定通用参数,因此不允许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>。然后,您的模型/视图模型将不得不通过界面展示集合,但是没有任何东西阻止您分别获得ListObservableCollection的支持实现。

+0

不,这只是一个例子。我的实体包含许多类型的列表。指定所有类型不是个好主意 – hungryMind 2012-02-02 10:50:36

+0

为什么你的界面不能返回'ICollection's?你的实现返回'ICollection's?那么每个实现都可以返回'ICollection'的不同实现? – Lukazoid 2012-02-02 11:13:18

+0

有关我的意思,请参阅@ oleksii的答案,这就是我的愿望。 – Lukazoid 2012-02-02 11:17:17