2010-06-28 67 views
3

我的小小心灵无法想出一个优雅的解决方案来解决这个问题。假设我有类如这样:简单课程+工厂的通用解决方案

public class Foo<T> 
    { 
     public RecordType Type { get; set; } 
     public T Value { get; set; } 
    } 

RecordType可能是这个样子:

public enum RecordType 
    { 
     EmptyRecord, 
     BooleanRecord, 
     IntegerRecord, 
     StringRecord, 
     ByteRecord 
    } 

的目标是一致对待的IEnumerable<Foo<T>>的迭代和/或对RecordType开关和如果可能的话,尽量避免装箱固有类型的同时执行动作。此外,如果使用工厂来创建这些Foo的工厂方法,那将是非常好的。

我已经摸索了一些基类或接口的通用性的快速实现,没有什么我想出来的,看起来很简单的问题。

小编辑: 我应该提到我的主要目标是使用.Value而不强制在调用者上强制转换。

+1

T是否以任何方式与RecordType相关? – Grzenio 2010-06-28 14:46:57

+0

好问题,是的,假设T分别是bool,int,string,byte [](对于这个例子) – Marc 2010-06-28 14:47:38

回答

2

你可以将非通用接口的IFoo:

public interface IFoo 
{ 
    RecordType Type { get; set; } 
} 

这是由通用Foo类实现:

public class Foo<T> : IFoo 
{ 
    public T Value { get; set; } 
} 

,并创建一个用于创建依赖于记录类型一个Foo实例的工厂方法:

public static IFoo CreateFoo(RecordType type) 
{ 
    switch (type) 
    { 
     case RecordType.Bool: return new Foo<bool>(); 
     // ... 
    } 
} 

一旦以这种方式创建了Foo实例,就不能访问价值,因为你还不知道类型参数。但你可以检查使用类型属性的类型,并做适当的转换:

IFoo foo = CreateFoo(RecordType.Bool); 

if (foo.Type == RecordType.Bool) 
{ 
    Foo<bool> boolFoo = (Foo<bool>)foo; 
    bool value = boolFoo.Value; 
} 

如果您有与富贵对象的作品,例如方法:

void DoIt<T>(IEnumerable<Foo<T>> foos) 
{ 
    foreach (Foo<T> foo in foos) 
    { 
     Qux(foo.Value); 
    } 
} 

,并有一个枚举IFoo的对象,你可以施放/ OfType说:

IEnumerable<IFoo> foos = // ... 
DoIt<bool>(foos.OfType<Foo<bool>>()); 

所以,本质上,你可以使用美孚<牛逼>当你在编译时知道T和IFoo的,如果你知道T只在运行时。 IFoo在运行时需要一张支票将它变成一个T的Foo <T>。

+0

感谢您的回答。我之前想到了一个变种,并且无法抽象出将'IFoo'强制转换为'Foo '的调用者。在任何时候,我通过工厂创建了一个'IFoo'集合,我需要调用者知道T并获得一个子集,或者在Type的迭代体开关中投入Foo 。我想我想把这个静态语言弯曲得太远。感谢您确认我的怀疑!也许我原本应该问一下,有什么更好的方法来做到这一点。 =) – Marc 2010-06-28 15:31:51