混合泛型,非泛型和基类设计问题

时间:2018-12-01 22:57:15

标签: c#

我的应用程序处理不同格式的数据。对于这个示例,我们说两个:TypeA和TypeB。因此,我创建了一个IFormatter接口:

interface IFormatter
{
   bool SomeOtherProp { get; }
   string Serialize(object o);
   T Deserialize<T>(string s);
}

然后我为实现创建了两个类:

class TypeAFormatter : IFormatter
{
}

class TypeBFormatter : IFormatter
{
}

我还有第3个容器类型类。这包含内容类型和序列化/格式化的数据:

public Content
{
  public string ContentType { get; private set; }
  public byte[] Data { get; private set; }
}

在我的应用程序的一个区域中,我负责创建Content对象:

void SomeMethodForTypeA()
{
   _content = new Content(new TypeAFormatter(), theContent);
}

void SomeMethodForTypeB()
{
   _content = new Content(new TypeBFormatter(), theContent);
}

Content的构造函数执行以下操作:

Content(IFormatter formatter, object content)
{
  Data = formatter.Serialize(content);
}

在我应用的另一个区域,我有一个IFormatter列表:

List<IFormatter> lstFormatters;

当数据输入时,我遍历列表并为输入的数据类型选择正确的格式化程序,然后调用Deserialize方法:

formatter.Deserialize<T>(data);

所以一切正常。

问题是,IFormatter接口反序列化是我所需要的泛型,但是TypeAFormatter可以处理任何类型T,而TypeBFormatter仅用于处理字符串。

所以我最终这样做了:

    public override string Serialize(object obj)
    {
        if (obj.GetType() != typeof(string))
            throw new Exception("must be string");

    public override T Deserialize<T>(string obj)
    {
        if (typeof(T) != typeof(string))
            throw new Exception("must be string);

这也是“有效的”。但是我不喜欢手动类型检查。我最初是将IFormatter改为IFormatterT并使它们看起来像这样:

public class TypeAFormatter<T> : IFormatter<T>
public class TypeBFormatter : IFormatter<string>

这在创建方面解决了问题,但是我没有IFormatterT的列表,并且在没有一堆反射的情况下调用类型化方法,然后无论如何它最终都被装箱作为对象。

任何方法都可以在不需要进行类型检查的地方进行,但是仍然可以为反序列化而通用地调用它们吗?

1 个答案:

答案 0 :(得分:1)

同时具有通用和非通用版本的接口,并根据您是否知道编译时类型来使用它们。

interface IFormatter
{
   string Serialize(object o);
   object Deserialize(string s);
}

interface IFormatter<T> : IFormatter
{
   string Serialize(T o);
   T Deserialize<T>(string s);
}

然后,IFormatter<T>的实现会将非通用的SerializeDeserialize的实现转发给它们的通用副本。同样,非泛型方法将嵌入适当的类型检查-通常在实现泛型版本的类中实现,因此可以访问类型参数T。像这样:

public string Serialize(object o)
{
    if (!(o is T)) throw ...;
    return Serialize<T>(o);
}

public string Serialize<T>(T o)
{
    // actual serialization code
}

此外,您可能希望在非通用版本中有一个方法来检查实现是否可以处理特定类型:

CanFormat(Type type);  // in case you know the type only
CanFormat(object obj); // in case you know the value

然后,您可以像这样选择正确的格式化程序:

var formatter = allFormatters.FirstOrDefault(f => f.CanFormat(myType));