2009-09-01 43 views
4

我有以下代码的情况,我怀疑可能有点dodgey:访问静态方法在泛型类在C#

我有一个类:

abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass 

该类DataAccessBase也有这其中一个语句创建使用枚举值本身派生类的实例的静态工厂方法来决定哪些派生类型创建:

static IDataAccess CreateInstance(TypeToCreateEnum) 

现在,TY从DataAccessBase<T>衍生PES本身不是通用的,他们指定类型为T:

class PoLcZoneData : DataAccessBase<PoLcZone> // PoLcZone is derived from AnotherAbstractClass 

到目前为止,我不知道这是否是推好使用泛型的限制,但我真的很关心的是如何首先访问静态CreateInstance()方法:

我现在这样做的方式是简单地通过任何类型T,其中T:AnotherAbstractClass。特别是我本身通过AnotherAbstractClass。这样可以很好地进行编译,但是在我看来,将任何类型传递给泛型类只是为了获得静态的数据有点不方便。

其实我已经简化了局面有所为DataAccessBase<T>是继承链中的较低水平,但静态工厂方法都存在一个中间层与如PoLcZoneData为最衍生的不是通用唯一的一级类。

这种安排是什么人民的想法?

+0

这是什么语言? – 2009-09-01 03:18:50

+0

对不起,它的C#。忘了添加到标题。 – MrLane 2009-09-01 03:19:46

回答

9

你被允许有一个非通用类的同名......也许是这样的:

abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass 
{ 
    ... 
} 
static class DataAccessBase 
{ 
    public static IDataAccess CreateInstance(TypeToCreateEnum) {...} 
} 

现在你可以使用DataAccessBase.CreateInstance没有任何多余的T。通常情况下,您可以拨打internal方法DataAccessBase<T>DataAccessBase - 虽然我怀疑在您的情况下,您可能还需要一点反思/ MakeGenericType

0

我不认为这种设计有什么问题,特别是如果您使用模板参数来指定实现细节。我所建议的只是让工厂的功能不是静态的,而只是一个独立的。这对我来说是最清晰的方式。

如果你想以某种方式封装它,我会建议一个命名空间或命名约定。

又一解决方案将只是躲在目前你在做什么,通过定义也许像这样一类DataAccessBase的:

typedef DataAccessBase<AnotherAbstractClass> DataAccessBaseFactory; 

这是我最推荐的解决方案,但它留下的创建函数为静态如果你绝对想要它。

+0

@killerfox这是c# – 2009-09-01 03:24:43

+0

好吧,在这种情况下,我想唯一的选择是将工厂函数封装在一个单独的类而不是名称空间 – 2009-09-01 03:36:01

2

我前段时间遇到类似的问题(“如何重载静态方法”),我用Reflection解决了它。

这里是我的情况:

1)public abstract class AuditObject<T> : ActiveRecordBase<T>(是的,我使用ActiveRecord)和

2)public class Employee : AuditObject<Employee>

在他们两个我定义了一些静态方法,例如

public static DataTable GetLookupTable(String where, Int32 topRows) 
{ 
    return doExtremelyCleverStuffToFetchData(where, topRows); 
} 

(在#2你需要public **new** static否则你会得到一个编译器警告)

由于代码是,当我打电话例如

DataTable myList = AuditObject<T>.GetLookupTable("inactive = 0", 100); 

...,T是雇员,静态方法不是“被覆盖的”,即所执行的一个是在方法(1),而不是(2)。

所以在(1)我修改了静态方法(在这个例子中,GetLookupTable)是这样的:

public static DataTable GetLookupTable(String where, Int32 topRows) 
{ 
    DataTable tbl = null; 

    Boolean hasOverride = hasMethodOverride("GetLookupTable"); 

    if (hasOverride) 
    { 
     tbl = invokeStaticMethod<T>(
      "GetLookupTable", new Object[2] { where, topRows }) 
      as DataTable; 
    } 
    else 
    { 
     tbl = doExtremelyCleverStuffToFetchData(where, topRows); 
    } 

    return tbl; 
} 

以下是我发现如果静态方法存在:

private static Boolean hasMethodOverride(String methodName) 
{ 
    var methodQuery = 
     from method in typeof(T).GetMethods(
      BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod) 
     where method.Name == methodName 
     select method; 

    return methodQuery.Count() > 0; 
} 

而且这里是如何调用“覆盖”方法:

public static Object invokeStaticMethod<T>(String MethodName, Object[] Args) 
{ 
    return typeof(T).InvokeMember(MethodName, 
     BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, 
     null, null, Args); 
} 

瞧!当我致电DataTable myList = AuditObject<T>.GetLookupTable("inactive = 0", 100); 并且T是Employee时,我从Employee类中定义的静态方法获得结果。

希望这有助于

季米特里斯