2012-01-02 79 views
2

我正在寻找一个C#替代C++ typedefs或特定类在特定情况下。我知道没有直接的等价物,但是对于这个特定的问题,可能还有其他解决方案?C#中的静态派生类型?

这是我想要做的。我正在编写一个有三种相关类型的框架。视图,后备存储和工厂。所有三个接口将会有多个实现。视图与工厂之间存在1-1关系,视图与存储之间存在1-N关系。一个具体的impl。的框架看起来像这样:

Storage : IStorage<int> ... 

View : IView<Storage> ... // And IView<T> : IViewNonGeneric further up.. 

Factory : IFactory<Storage> { 
    // This needs to take a concrete storage type as arg 
    IViewNonGeneric CreateView(Storage s) ... 

    Storage CreateStorage() ... 
} 

View类是框架用户最重要的类;其他的都是一些实现细节。因此,根据View类来定义工厂(而不是根据存储)看起来更自然。在C++中,这将是简单的,只需添加一个typedef到视图,并在工厂里使用它,就像这样:

class IView<typename T> { typedef T TStorage; ... 

class IFactory<typename T> { 
    IViewNonGeneric CreateView(typename T::TStorage s) ... 

在C#中,我们显然不具备的typedef或traits类。有没有其他的方式来达到预期的效果?也就是说,是否可以使用View作为Factory的通用参数,并从View中派生出具体的Source类型?

+1

是不够的,使用'where'仿制药申报约束的类型必须实施? – Tigran 2012-01-02 10:38:03

回答

3

C#中的泛型绝对不如C++中的模板强大。但是,C#确实有一些非常强大的C++没有的东西:反射。

在视图类中定义一个方法(静态或实例)应该很容易,该方法将返回存储类的具体类型。然后,您可以使用Type.GetConstructor动态查找存储类的构造函数,并使用ConstructorInfo.Invoke方法调用它。

此外,您可以探索使用您可以分配给视图类的自定义属性。怎么样是这样的:

[StorageType(typeof(MyStorage1) ] 
class MyView1 { ... } 

然后使用反思的typeof(MyView1),看它是否已StorageTypeAttribute与它相关联。

+0

谢谢你的建议。这可能是我得到的最接近的,但不幸的是它不会工作,因为它需要更改工厂功能签名。 – 4ZM 2012-01-02 10:40:27

+0

不知道我跟着你为什么你不得不改变工厂功能签名。你可以使工厂成为一个通用的类。或者...您可以将反射与属性结合起来 – DXM 2012-01-02 10:46:56

+0

在IFactory 接口中我有:T CreateStorage()(其中T:IStorage)。什么信号。如果IFactory接口的通用参数被改变来表示一个视图而不是存储器,这个函数的功能是什么? – 4ZM 2012-01-02 11:12:15

0

我想是你想要什么:

public interface IStorage<T> 
{ 
} 

public class IntStorage : IStorage<int> 
{ 
} 

public interface IFactory<S, T> where S : IStorage<T> 
{ 
    IView<S, T> CreateView(S storage); 
} 

public interface IViewNonGeneric 
{ 
} 
public interface IView<S, T> : IViewNonGeneric where S : IStorage<T> 
{ 
} 

public class IntView : IView<IntStorage, int> 
{ 
} 

public class IntFactory : IFactory<IntStorage, int> 
{ 
    public IntView CreateView(IntStorage storage) 
    { 
     // create the view 
    } 
    // private interface implementation 
    IView<IntStorage, int> IFactory<IntStorage, int>.CreateView(IntStorage storage) 
    { 
     return CreateView(storage); 
    } 
} 

...