Является ли это подходящим использованием обобщений и динамического типа данных C #? - PullRequest
3 голосов
/ 13 июля 2011

Проблема, с которой я столкнулся, заключается в том, что мы создаем слой доступа к данным, используя наш существующий ORM (старый называется Gentle), с идеей перехода на что-то вроде Fluent NHibernate. Есть несколько запросов, в которых мы должны добавить пользовательские предложения в SqlBuilder в нашей существующей установке, поэтому, например, при извлечении некоторых объектов person мы можем добавить предложение, например:

"PersonId in (SELECT PersonId from Orders where OrderValue > " + orderValue + " and OrderName = " + orderName

Дело в том, что параметры добавляются непосредственно в строку, а не как параметризованный запрос, в Gentle можно добавить его как параметризованный запрос, и это то, над чем я работал. Все наши DAL наследуются от базового GentleDAL, это класс, который фактически создает запрос Gentle, добавляет предложения и параметры и т. Д. Чтобы добавить параметризованное предложение в Gentle, вам нужно сделать две вещи с вашим объектом SqlBuilder, вам нужно вызовите sb.AddConstraint(string clause), чтобы добавить свое предложение, а затем для каждого параметра, который вы должны вызвать sb.AddParameter(string name, Type type), вы можете затем построить свой объект SqlStatement из этого, и только после этого вы можете установить значение для вашего параметра, где вы вызываете stmt.SetParameter(string name, object value).

Способ, которым я представил эти параметры / предложения, состоит в том, что я создал класс с именем GentleClauseCollection, который содержит предложения и параметры и имеет методы Add и Get для обеих этих вещей. Предложения являются просто строками и хранятся внутри списка, а параметры хранятся в классе GentleParameter, который использует обобщенные значения. Полный код для GentleParameter выглядит следующим образом.

public class GentleParameter<TParamType>
{       
    public string Name { get; private set; }
    public TParamType Value { get; private set; }
    public Type ParameterType  {get { return typeof (TParamType); }}
    public GentleParameter(string parameterName, TParamType parameterValue)
    {
        Name = parameterName;
        Value = parameterValue;
    }
}

В .NET нет такой коллекции, которая позволила бы мне хранить GentleParameter для разных значений TParamType в одной коллекции, однако это можно сделать с помощью DLR. В моем классе GentleCollection я сохраняю параметры в списке и получаю параметры из этого класса как IEnumerable. Метод Add в моем классе позволяет добавлять только GentleParameter, поэтому я знаю, что мои параметры всегда будут иметь поля Name, Value и ParameterType, к которым я могу получить доступ.

Мои вопросы: учитывая, что я могу пожертвовать родовыми типами и изменить свой класс Value свойства Value на «object» вместо T, я слишком усложнил вещи, используя динамические, каковы плюсы и минусы обоих подходов? Есть ли третий способ сделать это, о котором я не задумывался, и какое значительное влияние на производительность я, скорее всего, увижу при использовании динамического, учитывая, что все вызовы методов с использованием динамических объектов будут компилироваться во время выполнения?

Заранее спасибо за помощь.

Ответы [ 2 ]

2 голосов
/ 13 июля 2011

Поскольку sb.SetParameter не является универсальным и ожидает object, я бы не стал GentleParameter универсальным и, следовательно, я бы не использовал DLR.

1 голос
/ 13 июля 2011

Использование динамического не кажется мне слишком сложным.Вызовы методов разрешаются во время выполнения, и он кэшируется, итоговый вызов, вероятно, в среднем примерно в 10 раз медленнее (мы говорим об наносекундах).Так что это зависит от того, как вы собираетесь использовать его, если это имеет смысл.

Если вы всегда собираетесь использовать его как тип Object, тогда да, вам не нужно использовать динамический тип, не то чтобы это повредило бы что-либо.

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

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

 ...

private void HelperDoStuffWithGenericParam<T>(GentleParameter<T>param){

        //Do stuff you have the static typing
}
...