Как мне провести рефакторинг трех операций с базами данных, которые отличаются только вызовом метода? - PullRequest
0 голосов
/ 20 декабря 2009

У меня есть три операции с базой данных, например:

public void Add<T>(T entity)
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable)
        {
            foreach (var item in (IEnumerable) entity)
            {
                Session.Save(item);
            }
        }
        else
        {
            Session.Save(entity);
        }

        transaction.Commit();
    }
}

public void Update<T>(T entity)
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable)
        {
            foreach (var item in (IEnumerable) entity)
            {
                Session.Update(item);
            }
        }
        else
        {
            Session.Update(entity);
        }

        transaction.Commit();
    }
}

public void Delete<T>(T entity)
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable)
        {
            foreach (var item in (IEnumerable)entity)
            {
                Session.Delete(item);
            }
        }
        else
        {
            Session.Delete(entity);
        }

        transaction.Commit();
    }
}

Как видите, единственное, что отличается, - это Session.[something] часть. Как бы я реорганизовал это только в один метод?

Ответы [ 3 ]

0 голосов
/ 20 декабря 2009

Вы можете передать Действие , которое должно быть выполнено для объекта:

public static void DoInTransaction<T>(this T entity, Action<T> action)
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable<T>)
        {
            foreach (T item in (IEnumerable<T>) entity)
            {
                action(item);
            }
        }
        else
        {
            action(entity);
        }

        transaction.Commit();
    }
}

Пример:

entity.DoInTransaction(Session.Save);
entity.DoInTransaction(Session.Update);
entity.DoInTransaction(Session.Delete);
0 голосов
/ 23 декабря 2009

Делегаты выглядят здесь как хорошее решение, как объяснили другие участники. Еще один возможный рефакторинг, который может упростить внутреннюю логику, - это функция, которая возвращает IEnumerable Если переданный объект является IEnumerable, просто верните его; в противном случае создайте одноэлементное перечисление с переданным объектом и верните перечисление. Это превратит это:

if (entity is IEnumerable)
{
    foreach (var item in (IEnumerable) entity)
    {
       Session.Save(item);
    }
}
else
{
    Session.Save(entity);
}

в это:

foreach (var item in ForceEnumerable(entity))
    {
       Session.Save(item);
    }
0 голосов
/ 20 декабря 2009

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

private void DatabaseAction<T>(T entity, Action<T> action) 
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable)
        {
            foreach (var item in (IEnumerable) entity)
            {
                action(item);
            }
        }
        else
        {
            action(item);
        }

        transaction.Commit();
    }
}

Затем проведите рефакторинг ваших 3 методов:

public void Add<T>(T entity)
{
    DatabaseAction(entity, item => Session.Save(item));
}

public void Update<T>(T entity)
{
    DatabaseAction(entity, item => Session.Update(item));
}

public void Delete<T>(T entity)
{
    DatabaseAction(entity, item => Session.Delete(item));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...