Как использовать Dynamic LINQ для одновременного запроса выражений для разных типов объектов - PullRequest
0 голосов
/ 05 января 2012

Я экспериментировал с Dynamic LINQ в качестве решения сценария, в соответствии с которым мне нужно разрешить пользователю выбирать серию файлов на основе назначенного ему «тега».Например,

File A - tagged as "a",
File B - tagged as "b",
File C - tagged as "c",
File D - tagged as "d" and "a"

Поэтому, если я хочу найти все файлы, помеченные как "a", я набрал бы:

tag = "a"

Я бы получил файл a и файл d.Но я также мог бы набрать

tag = "a" OR tag = "b"

Поэтому я бы получил файлы a, b и d

Кстати, это всего лишь пример!

Итак, учитывая этот сценарийЯ могу добиться этого, используя следующий код:

List<FileMeta.Filetag> tags = fetchAllTags(file); //this fetches the tags from the file and places them in a list
            if (tags != null) //just in case
            {
                //declare the type of parameter we are looking for - in this case a "tag"
                var p = Expression.Parameter(typeof(string), "Tag");
                //setup the lambda parser to accept the param type, and use the expression
                var z = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, equation);

                //for each tag in this file
                foreach (FileMeta.Filetag t in tags)
                {
                    //if it hasn't been found yet
                    if (!bFound)
                    {
                        bFound = (bool)z.Compile().DynamicInvoke(t.tag);
                    }
                }
            }

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

У меня проблема со следующим сценарием.

«Теги» для этих файлов фактически сохраняются в информации о альтернативном потоке для файла.вместе с другой информацией, которая фактически является «мета» информацией о файле.Файл может содержать 1 или более фрагментов метаинформации.Из-за этого все сериализуется в один поток с файлом в виде данных XML из типизированных объектов - вы, возможно, заметили, что список в приведенном выше коде имеет тип FileMeta.Filetag.Все объекты наследуются от базового объекта, называемого Filemetabaseobject.

Так что я не могу разобраться, если я хочу посмотреть на другой тип объекта, например объект Filedate, на тот жевремя как объект Filetag, возможно ли с помощью Dynamic LINQ передать, скажем, каждый объект его базового типа (Filemetabaseobject) и каким-то образом выполнить приведение?

Я спрашиваю, потому что в идеальном сценарии я быхотелось бы иметь возможность запрашивать эту метаинформацию, например, например, tag = "a" AND date = "01/01/2012", но у меня проблема в том, что "tag" будет в объекте Filetag, а«date» будет в объекте Filedate, очевидно, в виде свойств: например, в упрощенном сценарии:

public class Filemetabaseobject
{

}
public class Filetag : Filemetabaseobject
    {
        public string tag { get; set; }
    }
public class Filedate : Filemetabaseobject
{
    public string date { get; set; }
}

Есть ли решение для этого?

Заранее спасибо!

Извините, я добавил, что пользователь может напечатать практически любой тип запроса, например (tag = "a" AND tag = "b") ИЛИ tag = "c", или они могут затем напечатать (tag = "a" AND)tag = "b" AND tag = "c"), например.

Ответы [ 2 ]

0 голосов
/ 11 января 2012

С помощью предложения, сделанного sq33G выше относительно наличия абстрактных классов, предоставляющих свойство value, я смог решить эту проблему.

В основном все типы (включая теги) наследуются от объекта Filemetabaseobject,переопределяемое свойство, называемое «значением», для которого установлено все, что вы хотите выставить для поиска, вы можете из унаследованного объекта установить значение get, чтобы получить то, для чего вы хотите, чтобы этот объект был найден.Следуя реализации метода Dynamic LINQ ParseLambda, вы можете передать унаследованный тип объекта как эквивалент его базового класса, и он все еще сможет обращаться к любому типу унаследованного объекта, основываясь на возможности увидеть это переопределенное свойство:1006 *

0 голосов
/ 05 января 2012

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

public abstract class FileMetabaseObject {
    public abstract string Value { get; }
}

public class FileTag : FileMetabaseObject {
    public string Tag { get; set; }
    public override string Value { get { return Tag; } }
}

Тогда вы сможете использовать

List<Func<FileMetabaseObject,bool>> whereClauses = 
    new List<Func<FileMetabaseObject,bool>> { 
        m => m.Value == "foo", 
        m => m.Value == DateTime.Today.ToShortDateString() };

bool meetsCriteria = whereClauses.
    All(criteria => fileMetadataColl.
        Any(meta => criteria(meta));

Не совсем понятно, насколько полезен динамический Linq здесь.

...