Я создаю библиотеку, которая извлекает HTML-таблицы из Интернета и преобразует их в объекты. У меня есть объект ColumnConfigurator, который предварительно настраивает расположение конкретной таблицы:

config.Column().Text().MapTo(/*Class.TextPropertyName*/); //What I want to be able to do
config.Column().Date().MapTo(/*Class.DatePropertyName*/);

Приведенный выше код - это общее представление о том, что я хочу делать в конфигурации (обратите внимание, что первая функция создает новый столбец и возвращает его, а последующие методы устанавливают конфигурацию объекта), а затем, когда таблица сопоставлен с Я хотел бы получить параметр, переданный в MapTo, и автоматически преобразовать его в правильное свойство данного объекта.

Вот что меня больше всего сбивает с толку: я хочу сделать основной объект таблицы универсальным (ParsingTable<T>), чтобы теоретически можно было сопоставить любой объект. Это означает, что ни одно из свойств не доступно заранее. Я хотел бы передать T.Property в метод, чтобы он знал, как выполнять автоматическое сопоставление. Есть ли способ сделать это? Я немного читал об отражении, но слышал, что это плохо для производительности.

0
w0f 28 Июн 2017 в 21:19
У вас много чего происходит, поэтому непросто понять, о чем именно вы спрашиваете. Если вы хотите иметь такой синтаксис: var item = config.SomeMethod().SomeOtherMethod();, тогда вам понадобятся методы расширения . Если вы хотите использовать универсальные шаблоны с заданными свойствами без отражения, вам нужно найти общий абстрактный (например, интерфейс, абстрактный класс, базовый класс) и ограничить общий метод этим абстрактным. Тогда вы сможете получить доступ к любому из членов этого абстрактного из вашего универсального метода.
 – 
maccettura
28 Июн 2017 в 21:43

1 ответ

Лучший ответ

Для получения информации о создании свободного интерфейса (что вы делаете для конфигурации) см. Здесь: создание API это свободно

Чтобы метод MapTo принял имя свойства из универсального класса, вы получите что-то вроде этого:

public class ParsingTable<T>
{
   /*** All the other stuff ***/

   public static IColumnConfiguration MapTo(this IColumnConfiguration config, Expression<Func<T, object>> property)
   {
      if (property.Body is MemberExpression)
      {
         config.Property = (property.Body as MemberExpression).Member as PropertyInfo;
      }
      else
      {
         config.Property = (((UnaryExpression)property.Body).Operand as MemberExpression).Member as PropertyInfo;
      }
   }
}

public interface IColumnConfiguration
{
     PropertyInfo Property { get; set; }
}

Затем, когда вы выполняете синтаксический анализ, вы должны вызвать PropertyInfo.SetValue () для каждого значения / столбца.

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

Обратите внимание, я взял часть приведенного выше кода отсюда: http://blog.raffaeu.com/archive/2010/06/26/how-to-write-fluent-interface-with-c-and-lambda.aspx < / а>

1
Michael Weinand 28 Июн 2017 в 22:35