Доступ к статическим методам в общем классе в c # - PullRequest
4 голосов
/ 01 сентября 2009

У меня есть следующая ситуация в коде, которая, я подозреваю, может быть немного хитрой:

У меня есть класс:

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

Этот класс DataAccessBase также имеет статический метод фабрики, который создает экземпляры своих производных классов, используя значение перечисления в каком операторе, чтобы решить, какой производный тип создать:

static IDataAccess CreateInstance(TypeToCreateEnum)

Теперь типы, полученные из DataAccessBase<T>, сами по себе НЕ являются общими, они указывают тип для T:

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

Пока что я не уверен, что это расширяет границы правильного использования генериков, но меня действительно беспокоит то, как в первую очередь получить доступ к статическому методу CreateInstance():

Способ, которым я сейчас занимаюсь, - просто передать любой тип T, где T: AnotherAbstractClass. В частности я прохожу AnotherAbstractClass сам. Это позволяет выполнять компиляцию просто отлично, но мне кажется, что передача любого типа в универсальный класс просто для получения статики - это немного хитро.

Я на самом деле несколько упростил ситуацию, так как DataAccessBase<T> является нижним уровнем в цепочке наследования, но статические фабричные методы существуют на среднем уровне, а классы, такие как PoLcZoneData, являются наиболее производными на единственном уровне, который не универсальный.

Что думают люди об этой договоренности?

Ответы [ 3 ]

10 голосов
/ 01 сентября 2009

Вам разрешено иметь неуниверсальный класс с тем же именем ... возможно что-то вроде:

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

Теперь вы можете использовать DataAccessBase.CreateInstance без каких-либо избыточных T. Как правило, вы можете вызывать internal методы для DataAccessBase<T> из DataAccessBase - хотя я подозреваю, что в вашем сценарии вам также может понадобиться небольшое отражение / MakeGenericType.

2 голосов
/ 14 апреля 2010

Недавно я столкнулся с подобной проблемой («как перегрузить статические методы») и решил ее с помощью 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 - Employee, статический метод не «переопределяется», т.е. выполняется метод в (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.

Надеюсь, это поможет,

Димитрис

0 голосов
/ 01 сентября 2009

Я не думаю, что с этим дизайном что-то не так, особенно если вы используете параметр шаблона, чтобы указать детали реализации. Я хотел бы предложить, чтобы заводская функция была не статичной, а автономной. Это был бы самый ясный способ сделать это для меня.

Если вы хотите каким-то образом его инкапсулировать, я бы предложил пространство имен или соглашение об именах.

Еще одно решение - просто скрыть то, что вы сейчас делаете, определив тип DataAccessBase, например, так:

typedef DataAccessBase<AnotherAbstractClass> DataAccessBaseFactory;

Это мое наименее рекомендуемое решение, но оно оставляет функцию Create статичной, если вы абсолютно этого хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...