Общие методы подписи - PullRequest
       42

Общие методы подписи

2 голосов
/ 29 августа 2011

У меня есть класс доступа к данным, который загружает справочные данные. Каждый тип объекта будет выполнять свою собственную хранимую процедуру и возвращать набор результатов, специфичный для этого типа объекта. Затем у меня есть метод, который отображает возвращаемые значения из таблицы данных в сущность. Все типы сущностей имеют одинаковые открытые свойства Code и Name. Как я могу сделать этот метод универсальным для обработки типа сущности? Примерно так и должно быть, но свойства вызывают ошибку.

    private static T MapDataReaderToEntity<T>(IDataReader reader)
    {
        var entity = typeof (T);
        entity.Code = SqlPersistence.GetString(reader, "Code");
        entity.Name = SqlPersistence.GetString(reader, "Name");
        return entity;
    }

и я бы назвал это примерно так.

_sourceSystem = MapDataReaderToEntity<SourceSystem>(_reader);

Ответы [ 4 ]

4 голосов
/ 29 августа 2011

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

public interface IEntity
{
    string Code { get; set; }
    string Name { get; set; }
}

Теперь вы можете добавить общее ограничение к вашему методу:

public static T MapDataReaderToEntity<T>(IDataReader reader) where T : IEntity, new()
{
    T entity = new T();
    // More code here...
}

Обратите внимание, что вам также необходимо ограничение new() для фактического создания новой сущности; это означает, что любой аргумент универсального типа будет иметь конструктор без параметров.

3 голосов
/ 29 августа 2011

Если ваши сущности реализуют интерфейс с определенными свойствами Code и Name, вы можете использовать что-то вроде:

private static T MapDataReaderToEntity<T>(IDataReader reader)
    where T : IEntity, new()
{
    T entity = new T(); // typeof(T) would return the System.Type, not an instance!
    entity.Code = SqlPersistence.GetString(reader, "Code");
    entity.Name = SqlPersistence.GetString(reader, "Name");
    return entity;
}

Без интерфейса компилятор не сможет узнать о Code или Name свойства.Вам нужно будет вернуться к использованию Reflection или динамического кода, или некоторого другого неидеального механизма для определения этих свойств в время выполнения вместо во время компиляции.

2 голосов
/ 29 августа 2011

Вам необходимо добавить ограничение типа к MapDataReaderToEntity<T>, которое гарантирует, что любой T реализует установщики свойств Code и Name, а также конструктор без параметров.

1 голос
/ 29 августа 2011

Если у всех ваших сущностей есть свойства Code и Name, я бы предложил им реализовать интерфейс ICodedEntity со свойствами Code и Name, а затем определить ваш метод

private static T MapDataReaderToEntity<T>(IDataReader reader) where T : ICodedEntity, new()
{
    var entity = new T();
    ...     
}

тогда ваш код скомпилируется.

...