2

我有一组方法,每个方法都为各种类型的 T 返回一个 ObservableCollection,并且希望能够根据发送的枚举值编写一个返回这些方法的工厂方法。例如,假设我有以下高度现实的方法...

public ObservableCollection<Gribble> GetGribbles() {
  return new ObservableCollection<Gribble>();
}

public ObservableCollection<Gribulator> GenerateGribulators() {
  return new ObservableCollection<Gribulator>();
}

public ObservableCollection<Knepple> MakeKnepples() {
  return new ObservableCollection<Knepple>();
}

...以及以下枚举...

public enum ListNames {
  Gribbles,
  Gribulators,
  Knepple
}

然后我希望能够做到这一点......

Func<ObservableCollection<Gribble>> someGribbles = 
       MakeFunc<Gribble>(ListNames.Gribbles);

这样做的原因是我有一个带有这样签名的助手类......

public void GetList<T>(ListNames listName, 
  Func<ObservableCollection<T>> serviceCall, 
  Action<ObservableCollection<T>> handleList)

serviceCall 是获取列表的方法,handleList 是回调方法。目前,无论在何处调用此方法,代码都必须传递获取列表的实际函数。

然而,这被证明是一个糟糕的设计选择,因为这意味着如果代码的两个部分都为特定列表调用 GetList,它们可能会传入两个不同的服务调用,这将导致结果不一致。我想将服务调用封装在 MakeFunc 方法中,该方法将从 GetList 调用,这意味着使用 GetList 的代码永远不会看到实际的服务调用,因此不会做错任何事情。

我已经尝试了一些东西,但正在努力获得任何可以编译的东西。我得到的最接近的是以下......

public Func<ObservableCollection<T>> MakeFunc<T>(ListNames listName) {
  switch (listName) {
    case ListNames.Gribbles:
      return GetGribbles;
    case ListNames.Gribulators:
      return GenerateGribulators;
    case ListNames.Knepple:
      return MakeKnepples;
    default:
      throw new ArgumentException("Unknown list name");
  }
}

...但这会产生编译器错误,类似于“ GetGribbles() has the wrong return type ”,并且当我将鼠标悬停在 MakeFunc 方法中的 GetGribbles 上时弹出的工具提示说

期望一个带有'ObservableCollection<T> GetGribbles()'签名的方法

有可能做我想做的事吗?如果是这样,谁能解释我做错了什么?

如果有任何区别,我将在 Visual Studio 2010 中使用 C# 4.0。

4

1 回答 1

4

好吧,如果GribbleGribulatorKnepple类共享一个公共基类型或实现一个公共接口,您可以这样做:

public Func<ObservableCollection<ICommonInterface>> MakeFunc(ListNames listName) 
{
   ...
}

如果它们没有通用的基本类型或接口,则必须这样做:

public Func<ICollection> MakeFunc(ListNames listName) 
{
   ...
}

诚然,这不是一个很好的解决方案。注意:您可以替换ICollectionINotifyCollectionChanged您最需要的任何非通用接口。

在这两种情况下,您都必须依赖调用者来指定数据类型(即使调用者也指定了枚举值)。所以,你也可以摆脱枚举,然后去做这样的事情:

public Func<ObservableCollection<T>> MakeFunc<T>() 
{
  if (typeof(T) == typeof(Gribble))
      return () => GetGribbles() as ObservableCollection<T>;
  if (typeof(T) == typeof(Gribulator))
      return () => GenerateGribulators() as ObservableCollection<T>;
  if (typeof(T) == typeof(Knepple))
      return () => MakeKnepples() as ObservableCollection<T>;
  throw new ArgumentException("Unknown list name");
}

然后调用者可以简单地写:

var gribblesFunc = MakeFunc<Gribble>();
于 2013-06-21T00:03:16.437 回答