Делегированный - правильно ли мое использование делегатов? - PullRequest
1 голос
/ 21 октября 2010

Я создал класс, основной задачей которого является получение данных из БД и сопоставление их с каким-либо объектом.Проблема в том, что один и тот же класс должен отображать разные устройства чтения данных на разные объекты.Итак, я попытался выбрать метод отображения с использованием делегатов.

Вот часть моего кода.См. Важные строки жирным шрифтом.

public class GetDetails<T>
{       
    **public delegate void DelegateMapping(T position, IDataReader reader);**
    **public DelegateMapping mappingMethod;**

    public T Get(T instance)
    {
        //Get IDs and Add to list
        _db.ExecuteReader(storedProcedure.ToString(), CommandType.StoredProcedure, reader =>
        {
            while ( reader.Read() )
            {
                **mappingMethod(instance, reader);**
            }

        }, parameterList.ToArray());

        return instance;
    }
}

И этот класс вызывает и использует класс "GetDetails"

public class PositionDB : DbBase
{
    public Position GetPositionDetails(string IDs)
    {
        GetDetails<Position> getIDs = new GetDetails<Position>(base.db);
        getIDs.storedProcedure = StoredProcedure.NET_ADM_GetPositionDetails;

        //Set the Delegated Method
        **getIDs.mappingMethod = MappingPositionDetails;**

        //Set Parameters
        getIDs.parameterList.AddInParam("PositionIds", DbType.String, IDs);

        //Return the PositionId Collection
        return getIDs.Get(new Position());
    }

    **private void MappingPositionDetails(Position position, IDataReader reader)
    {
        position.Id = reader["CompPositionId"];
        position.Description = reader["Description"];
        position.ExpirationDate = reader["ExpirationDate"];
        position.Title = reader["Title"];
    }**

}

Код работает нормально.

Вопросы:

  1. Правильно ли я использовал делегат?
  2. Такое решение может вызвать проблемы в будущем (производительность)?
  3. Есть еще однолучшее решение?

Большое спасибо

Себастьян

Ответы [ 2 ]

1 голос
/ 21 октября 2010

Чтобы конкретно ответить на ваши вопросы:

  1. Да, вы правильно использовали делегатов
  2. Да, это может вызвать проблемы из-за проблем параллелизма при многопоточности
  3. Iдумаю, я подробно описал одно возможное решение ниже

Я бы предложил три изменения:

  1. Переместите вызов делегата в метод (проблемы параллелизма, один поток может изменить отображениеделегировать, в то время как другой поток пытается получить к нему доступ, теперь пытается сопоставить считыватель с совершенно другим объектом, чем предоставленный)
  2. Используйте уже существующие универсальные делегаты Action / Func, не нужно определять свой собственный.
  3. Используйте лямбда-выражения для определения сопоставления, нет необходимости в дополнительных методах

Примечание: для 2 и 3 потребуется не менее .net 3.5.

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

public class GetDetails<T>
{       
    public T Get (T instance, Action<T, IDataReader> mappingMethod)
    {
        //Get IDs and Add to list
        _db.ExecuteReader(storedProcedure.ToString(), CommandType.StoredProcedure, reader =>
        {
            while ( reader.Read() )
            {
                mappingMethod(instance, reader);
            }

        }, parameterList.ToArray());

        return instance;
    }
}

Теперь вы можете использовать этот метод и в многопоточной среде.

Edit

только что понял, яэто только часть кода.Я исправил свое предложение, чтобы учесть это.

0 голосов
/ 21 октября 2010
  1. Да (есть некоторые улучшения, которые вы могли бы сделать, см. 3)
  2. Не в отношении производительности, возможно, некоторые проблемы с возможностью обнаружения.
  3. Я бы использовал полиморфизм, чтобы полностью исключить делегата для обнаружения. Возможно использование абстрактного метода / класса. Также в зависимости от того, какую версию .NET вы разрабатываете, вы можете использовать лямбды и простые типы.

public Action<Position, IDataReader> Mapping { get; set; }

Тогда

getIDs.Mapping = (position, reader) => 
    {
        position.Id = reader["CompPositionId"];
        position.Description = reader["Description"];
        position.ExpirationDate = reader["ExpirationDate"];
        position.Title = reader["Title"];
    };
...