Могу ли я выполнить рефакторинг функций, которые имеют похожие входы, но вызывают разные сервисы в одну универсальную функцию? - PullRequest
0 голосов
/ 28 марта 2019

Я ищу способ объединить х количество очень похожих функций CRUD в одну без необходимости использовать х количество операторов if else для проверки типа универсального.

У меня есть контроллеры Web API, с которых я хочу делать вызовы, например:

Service.Get<FooModel>(number, type, part, version); 

Это сделано для того, чтобы исключить необходимость иметь чрезвычайно похожую функцию для 40+ конечных точек API.Проблема заключается в том, что когда я получаю это в своем сервисе, я должен проверить тип предоставленного общего и сравнить с этими более 40 типами объектов в одной функции.Все модели в настоящее время наследуются от базовой унаследованной модели.

Текущая общая функция

(функции создания, обновления, удаления аналогичны):

public T Get<T>(string documentNr, string type, string part, string version) where T : InheritedModel, new()
{
    try
    {
        T model = new T();

        if (typeof(T) == typeof(InheritedModel))
        {
           using (var repo = new InheritedModelConsumer(ref _helper))
           {
                model = (T)repo.Get(documentNr, type, part, version);
           }
        }
        else if (typeof(T) == typeof(FooModel))
        {
            using (var repo = new FooModelConsumer(ref _helper))
            {
                model = (T)(object)repo.Get(documentNr, type, part, version);
            }
        }
        else if (typeof(T) == typeof(ComponentModel))
        {
            using (var repo = new ComponentModelConsumer(ref _helper))
            {
                model = (T)(object)repo.Get(documentNr, type, part, version);
            }
        }
        else if (typeof(T) == typeof(BarModel))
        {
            using (var repo = new BarModelConsumer(ref _helper))
            {
               model = (T)(object)repo.Get(documentNr, type, part, version);
            }
        }
        ... and so on
        ... and so on
        ...
        else
            throw new Exception("Type T structure not defined");

        return model;
    }
    catch (Exception)
    {

        throw;
    }
    finally
    {
        _helper.Dispose();
    }
}

Это работает, но если это возможно, я ищу что-то, что я могу сказать во время выполнения: "оУ меня есть этот объект типа T, и, поскольку я знаю, что все функции имеют одинаковые входные данные, я собираюсь создать экземпляр этого потребителя типа TConsumer, вызвать consumer.Get (входные данные), а затем вернуть объект T любому APIконтроллер вызвал меня. "

Редактировать

Пример использования простого класса-потребителя


    internal sealed class FooConsumer : RepositoryConsumer<Foo, FooRepository, FooFilter>
        {
            public FooConsumer(ref SqlHelper helper) : base(ref helper) { }

            public List<Foo> GetAll(string token)
            {
                return _repo.Get().Where(x => Extensions.StringContainsToken(x.AccountName, token)).ToList();
            }
        }

Репозиторий Потребитель, от которого наследуются все потребители.T - модель, K - репозиторий (пользовательский класс ORM), а O - фильтр для предложения WHERE, которое выполняет ORM.



     public abstract class RepositoryConsumer<T, K, O> : IDisposable, IRepositoryConsumer<T> where T : class, new() where K : Repository<T, O>, new() where O : QueryFilter, new()
        {
            /// <summary>
            /// Repository instance
            /// </summary>
            protected K _repo;

            /// <summary>
            /// Only constructor avaialble. MUst pass SqlHelper instance for transaction support
            /// </summary>
            /// <param name="sql"></param>
            public RepositoryConsumer(ref SqlHelper sql)
            {
                _repo = Activator.CreateInstance(typeof(K), new object[] { sql }) as K;
            }

            /// <summary>
            /// Allow consumer initializations in using statements
            /// </summary>
            public void Dispose()
            {

            }

            /// <summary>
            /// Create instance of T
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public virtual int Create(T data)
            {
                return _repo.Create(data);
            }

            /// <summary>
            /// Bulk create instances of T
            /// </summary>
            /// <param name="contract"></param>
            /// <returns></returns>
            public virtual int Create(BaseBulkable<T> contract)
            {
                return _repo.BulkCreate(contract);
            }

            /// <summary>
            /// Get an instance of T based on a single PK field id
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public virtual T Get(long id)
            {
                return _repo.Get(id);
            }

            /// <summary>
            /// Gets all instances of T
            /// </summary>
            /// <returns></returns>
            public virtual List<T> GetAll()
            {
                return _repo.Get();
            }

            /// <summary>
            /// Updates an instance of T
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public virtual int Update(T data)
            {
                return _repo.Update(data);
            }

            /// <summary>
            /// Updates an instance of T based on a single PK field id
            /// </summary>
            /// <param name="id"></param>
            /// <param name="data"></param>
            /// <returns></returns>
            public virtual int Update(long id, T data)
            {
                return _repo.Update(id, data);
            }

            /// <summary>
            /// Deletes an instance of T
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public virtual int Delete(T data)
            {
                return _repo.Delete(data);
            }

            /// <summary>
            /// Deletes an instance of T based on a single PK field id
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public virtual int Delete(long id)
            {
                return _repo.Delete(id);
            }
        }

...