Преобразование метода C # для использования обобщений, ссылающихся на свойство внутри - PullRequest
4 голосов
/ 21 июня 2011

Я хотел бы преобразовать метод для использования обобщений.В настоящее время он жестко закодирован для следующих типов:

  • DataContext.Document в частичном классе контекста данных и наследуется от object
  • DataContext.Documents также в этом частичном классе и наследуетсяот Linq.Table<Document>
  • Import.Document наследование от пользовательского класса ImportObject

Исходный метод:

public void ProcessDocuments(Delegate method, params object[] args)
{
    using (DataContext dc = new DataContext())
    {
        dc.ObjectTrackingEnabled = false;

        // Map from DataContext object to ImportObject
        Mapper.CreateMap<Document, Import.Document>();

        // Loop through DataContext objects
        foreach (Document d in dc.Documents)
        {
            Import.Document doc = Mapper.Map<Document, Import.Document>(d);
            args[0] = doc;
            method.DynamicInvoke(args);
        }
    }
}

Попытка:

public void ProcessImportObjects<TSource, TDestination>
    (Action<TDestination, ImportDataSource, int> processMethod, ImportDataSource importSource, int resultId)
{
    using (DataContext dc = new DataContext())
    {
        dc.ObjectTrackingEnabled = false;
        Mapper.CreateMap<TSource, TDestination>();

        foreach (TSource d in dc.Documents) // PROBLEM: Hard-coded reference to property on DataContext
        {
            TDestination doc = Mapper.Map<TSource, TDestination>(d);
            processMethod(doc, importSource, resultId);
        }
    }
}

(Здесь TDestination должно быть типа ImportObject, но я не уверен, как это выразить.)

Как показано накомментарий foreach должен ссылаться на свойство в DataContext, которое является IEnumerable<TSource>.Означает ли это, что мне нужно передать DataContext в качестве параметра или есть лучший способ?

1 Ответ

2 голосов
/ 21 июня 2011

Похоже, вам нужно параметризировать имя свойства в DataContext.Один из способов сделать это - передать функцию, которая принимает DataContext и возвращает ваше перечисляемое значение (Func<DataContext, IEnumerable<TSource>>), а затем вы передаете лямбду, например dc => dc.Document, в качестве этого параметра.

ДругойОпция, которая будет работать (но без защиты типов) - передать имя свойства в виде строки и затем использовать Reflection для доступа к нему.

public void ProcessImportObjects<TSource, TDestination>
    (Func<DataContext, IEnumerable<TSource>> dcProperty,
     Action<TDestination, ImportDataSource, int> processMethod,
     ImportDataSource importSource,
     int resultId)
{
    using (DataContext dc = new DataContext())
    {
        dc.ObjectTrackingEnabled = false;
        Mapper.CreateMap<TSource, TDestination>();

        foreach (TSource d in dcProperty(dc))
        {
            TDestination doc = Mapper.Map<TSource, TDestination>(d);
            processMethod(doc, importSource, resultId);
        }
    }
}
...