【问题标题】:generic methods with observablecollections具有可观察集合的泛型方法
【发布时间】:2013-09-29 15:27:32
【问题描述】:

这适用于使用 .Net 4.5 的 Windows 8.1 Store 应用

我发现自己为我拥有的每个“对象”复制了相同的代码。所以我试图创建一个更通用的方法来以我想要的方式获取所有数据。最初对我的不同对象来说,一切都是<Typed>,但现在我正在尝试使用通用的<Object>

    public async Task<ObservableCollection<object>>selectAll()
    {
        var Items = await Win8StorageHelper.LoadData("person.dat", typeof(ObservableCollection<object>));
        ObservableCollection<object> ItemsList = new ObservableCollection<object>();
        if (typeof(Int32) == Items.GetType())
        {
            //Not Needed anymore
        }
        else
        {
            ItemsList = (ObservableCollection<object>)Items;
        }
        _list.Clear();
        foreach (object item in ItemsList)
        {
            _list.Add(item);
        }

        return _list;
    }

我有我原来的集合 _frequencyList,现在有一个新的通用集合 _list:

    private ObservableCollection<win8Chores.Model.databaseTables.Frequency> _frequencyList;
    public ObservableCollection<Object> _list = new ObservableCollection<Object>();

我正在尝试这样调用我的新方法:

_frequencyList = await selectAll();

但是,我收到一个错误:

不能隐式转换类型 'System.Collections.ObjectModel.ObservableCollection' 到 'System.Collections.ObjectModel>observableCollection'

我需要做什么才能使此代码正常工作?我什至走在正确的轨道上吗?任何帮助表示赞赏。

更新: 这些是我试图为通用示例重构的原始方法:

    public async Task<ObservableCollection<Person>> selectAllPersons()
    {
        var personItems = await Win8StorageHelper.LoadData("person.dat", typeof(ObservableCollection<Person>));
        ObservableCollection<Person> personItemsList = new ObservableCollection<Person>();
        if (typeof(Int32) == personItems.GetType())
        {
            //Not Needed anymore
        }
        else
        {
            personItemsList = (ObservableCollection<Person>)personItems;
        }
        _personList.Clear();
        foreach (Person item in personItemsList)
        {
            _personList.Add(item);
        }

        return _personList;
    }

    public async Task<ObservableCollection<Frequency>> selectAllFrequencies()
    {
        var frequencyItems = await Win8StorageHelper.LoadData("frequency.dat", typeof(ObservableCollection<Frequency>));
        ObservableCollection<Frequency> frequencyItemsList = new ObservableCollection<Frequency>();
        if (typeof(Int32) == frequencyItems.GetType())
        {
            //Not Needed anymore
        }
        else
        {
            frequencyItemsList = (ObservableCollection<Frequency>)frequencyItems;
        }
        _frequencyList.Clear();
        foreach (Frequency item in frequencyItemsList)
        {
            _frequencyList.Add(item);
        }
        return _frequencyList;
    }
    public async Task<ObservableCollection<Chore>> selectAllChores()
    {
        var choreItems = await Win8StorageHelper.LoadData("chore.dat", typeof(ObservableCollection<Chore>));
        ObservableCollection<Chore> choreItemsList = new ObservableCollection<Chore>();
        if (typeof(Int32) == choreItems.GetType())
        {
            //Not Needed anymore
        }
        else
        {
            choreItemsList = (ObservableCollection<Chore>)choreItems;
        }
        _choreList.Clear();
        foreach (Chore item in choreItemsList)
        {
            _choreList.Add(item);
        }
        return _choreList;
    }

【问题讨论】:

  • 为什么你现在使用object而不是你的特定类型?
  • 我正在为每种类型重写相同的方法。我认为它可以被重构,所以我不必一遍又一遍地重写相同的方法。这不是正确的方法吗?
  • 听起来像是泛型的案例。这使您可以保留类型并保持灵活性。
  • 不是通用的吗?我如何将上面的代码转换为“通用”?

标签: c# generics windows-runtime .net-4.5


【解决方案1】:

我认为您应该为此使用泛型;见Introduction to C# Generics

public async Task<ObservableCollection<T1>> selectAll<T1>(string filename)
{
    var Items = await Win8StorageHelper.LoadData(filename, typeof(ObservableCollection<T1>));

    if (Items is ObservableCollection<T1>)
    {
         return ((ObservableCollection<T1>)Items).ToList();
    }
    else
    {
        // empty or not the right type; depending on what the storage helper gives us
        return new ObservableCollection<T1>();
    }
}

被调用

var personList = selectAll<Person>("person.dat");
var frequencyList = selectAll<Person>("frequency.dat");

【讨论】:

  • 我也在查看它,我收到一条错误消息,提示找不到类型或命名空间“T”。您是否缺少参考或程序集。我检查了,我确实有使用 System.Collections.Generic;
  • 如果你做 Task>; 它应该可以工作或通过类类型或方法参数类型引用它;可能会发布一个更大的可运行示例(LINQpad 对此很有用),我们将能够提供更好的帮助
  • 如果我有 3 个对象都将使用此功能,是否与重写 3 次相同? - 查看我更新的问题
  • 一种方法就足够了;查看修改后的答案。
  • 当我尝试在我的代码中实现这一点时,我总是在“T”上遇到错误:找不到命名空间名称“T”...我错过了什么?包含该方法的类是否需要泛型
【解决方案2】:

你需要这样的东西

public async Task<ObservableCollection<T>> selectAllItems<T>(ObservableCollection<T> _list)
{
    var items = await Win8StorageHelper.LoadData(string.Format("{0}.dat",typeof(T).Name.ToLower()), typeof(ObservableCollection<T>));

    _list.Clear();
    if(!(items is ObservableCollection<T>))
    {
         return _list;
    }

    ObservableCollection<T> itemsList = (ObservableCollection<T>)items;        
    foreach (T item in itemsList)
    {
        _list.Add(item);
    }

    return _list;
}

_list是你需要添加所有项目的参数。

然后这样称呼它

selectAllItems(_personList);
selectAllItems(_frequencyList); //etc

【讨论】:

  • Sakthievel - 我在“T”上不断收到错误:找不到命名空间名称“T”...我在这里缺少什么?
  • 更新代码,方法签名变成这样public async Task&lt;ObservableCollection&lt;T&gt;&gt; selectAllItems&lt;T&gt;(ObservableCollection&lt;T&gt; _list)
  • 今晚我得试试这个。您知道在 Windows 应用商店应用中使用 .Net 4.5 进行泛型是否有任何区别?
  • 我认为不会有区别,因为两者都是 .net 框架的属性,而不是您使用的平台
  • 是的,我也是这么想的,但这不是我在错误列表中看到的。我在一个单独的项目上创建了一个测试类,代码看起来很好。不知道我在家里的项目是怎么回事......我会告诉你的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多