泛型类型的泛型类型?

时间:2014-11-17 12:05:24

标签: c# generics generic-programming

我有以下代码:

public abstract class ListPresenter<TView, TModel, TEntity> : Presenter<TView, TModel>
    where TView : IListView<TModel>
    where TModel : EntityListViewModel<TEntity>
    where TEntity : class, IEntity
{
    public ListPresenter(TView view, TModel model)
        : base(view, model)
    {
    }
}

有没有办法避免第三个参数?如果我尝试使用:

public abstract class ListPresenter<TView, TModel> : Presenter<TView, TModel>
    where TView : IListView<TModel>
    where TModel : EntityListViewModel<IEntity>

我明白了:

错误3类型&#39; PuntoVenta.ViewModels.SaleListViewModel&#39;不能用作类型参数&#39; TModel&#39;通用类型或方法&#39; PuntoVenta.Presentation.ListPresenter&#39;。来自&#39; PuntoVenta.ViewModels.SaleListViewModel&#39;没有隐式引用转换。 to&#39; PuntoVenta.ViewModels.EntityListViewModel&#39;。 C:\ Users \ Marc \ Dropbox \ Source \ PointOfSale \ PuntoVenta \ Presentation \ ListSalePresenter.cs 26 20 PuntoVenta.UI

甚至EntityListViewModel&lt; IEntity&gt;永远都是真的。

public abstract class EntityListViewModel<TEntity> : ViewModelBase, IEntityListViewModel<TEntity>
    where TEntity : class, IEntity 
{
    private BindingSource Entities { get; set; }

    private string searchQuery = string.Empty;

    public EntityListViewModel()
    {
        SearchQuery = string.Empty;
        Entities = new BindingSource();
    }

    public TEntity Selected
    {
        get { return Entities.Current as TEntity; }
        set { Entities.Position = Entities.IndexOf(value); }
    }

    public string SearchQuery
    {
        get { return searchQuery; }
        set
        {
            searchQuery = value;
            NotifyProperty("SearchQuery");
        }
    }

    public List<TEntity> DataSource
    {
        set
        {
            Entities.DataSource = value;
            NotifyProperty("DataSource");
        }
    }
}

public interface IEntity
{
    Guid Id { get; set; }

    DateTime DateCreated { get; set; }
    DateTime DateUpdated { get; set; }
}

public interface IListView<TModel> : IView<TModel>
    where TModel : ViewModelBase
{
    event EventHandler OnSearchQueryChanged;
    event EventHandler OnSelectRequested;
}

public abstract class ViewModelBase : IModel
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyProperty(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class SaleListViewModel : EntityListViewModel<SaleView>
{
    private bool _ShowPendingOnly = false;

    public SaleListViewModel()
    {
    }

    public bool ShowPendingOnly
    {
        get { return _ShowPendingOnly; }
        set
        {
            _ShowPendingOnly = value;
            NotifyProperty("ShowPendingOnly");
        }
    }

    public List<Customer> Customers { get; set; }
}

2 个答案:

答案 0 :(得分:1)

避免在EntityListViewModel的声明中使用泛型类型。

在这种情况下,无需使用泛型声明对象是否始终实现IEntity接口。

public abstract class EntityListViewModel
                      : ViewModelBase, IEntityListViewModel<IEntity>

您还需要将此课程中的任何引用更改为TEntity

public IEntity Selected
{
    get { return Entities.Current as IEntity; }
    set { Entities.Position = Entities.IndexOf(value); }
}

public List<IEntity> DataSource
{
    set
    {
        Entities.DataSource = value;
        NotifyProperty("DataSource");
    }
}

此时,您可以将ListPresenter声明为

public abstract class ListPresenter<TView, TModel>
                      : Presenter<TView, TModel>
                                 where TView : IListView<TModel>
                                 where TModel : EntityListViewModel<IEntity>

答案 1 :(得分:0)

您是否可以将IListViewEntityListViewModel限制为IEntity

public abstract class ListPresenter<TView, TModel> : Presenter<TView, TModel>
    where TView : IListView<IEntity>
    where TModel : EntityListViewModel<IEntity>

您可能需要IListViewEntityListViewModel协变:

public interface IListView<out T>