Как использовать делегат, чтобы получить по имени CompiledQuery - PullRequest
0 голосов
/ 01 июля 2010

Я пытаюсь найти и запустить CompiledQuery с указанным именем.Как получить доступ к скомпилированному запросу по имени и как затем вызвать делегата?

Вот как я могу получить - я получаю ошибку «Ошибка привязки к целевому методу»

public class ActivityRepository
{
    private readonly ActivityDataContext _db;

    public ActivityRepository()
    {
        _db = new ActivityDataContext();
    }

    public static Func<ActivityDataContext, int, IQueryable<ProjectObject>>
        GetCompiledLatestProjects = CompiledQuery.Compile
            ((ActivityDataContext db, int projectId) =>
             from c in db.projectObjects
             where c.projectId == projectId
             select c);

    public static Func<ActivityDataContext, Guid, IQueryable<Report>>
        GetCompiledReports = CompiledQuery.Compile
            ((ActivityDataContext db, Guid itemId) =>
             from c in db.Reports
             where c.reportObjectId == itemId
             select c);

// Другие скомпилированные запросы пропущены, но в результате получаются объекты IQueryable, которые реализуют общий интерфейс IProjectObject

    delegate IQueryable<IProjectObject> MyDelegate();

    static MyDelegate GetByName(object target, string methodName)
    {
            return (MyDelegate)Delegate.CreateDelegate
                (typeof(MyDelegate), target, methodName);
    }

    public IList<Results> GetResults(string reportName)
    {
            IQueryable<ProjectObject> projectItems = GetLatestProjectObjects(projectId, quantity);
        foreach (projectObject o in projectItems)
        {
            MyDelegate del = GetByName(this, reportName);
             var dbReport = (IProjectObject) GetCompiledReports(_db, o.itemId).FirstOrDefault();
// add results to List and return
         }
     }
}

1 Ответ

0 голосов
/ 02 июля 2010

Вы, вероятно, можете сделать какой-то долгий путь, пытаясь идентифицировать любые поля типа Func <...> с DataContext в качестве первого аргумента, возвращающего IQueryable, но вам может быть гораздо проще просто добавить пользовательский атрибут:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class DynamicQueryAttribute : Attribute { }

... который вы затем можете добавить в свое поле:

[DynamicQuery]
public static Func<ActivityDataContext, int, IQueryable<ProjectObject>>
    GetCompiledLatestProjects = CompiledQuery.Compile
        ((ActivityDataContext db, int projectId) =>
         from c in db.projectObjects
         where c.projectId == projectId
         select c);

Затем вы можете выбрать запрос на основе этого и его имя:

public static IQueryable<IProjectObject> ExecuteQuery(Type ownerType, string name, params object[] args)
{
    var query = typeof(ownerType)
        .GetFields(BindingFlags.Public | BindingFlags.Static)
        .Where(f =>
                (f.GetCustomAttributes(typeof(DynamicQueryAttribute), false).Length > 0)
                && (f.Name.ToLowerInvariant() == name.ToLowerInvariant()))
        .Select(f => (Delegate) f.GetValue(null))
        .SingleOrDefault();

    if (query == null)
        return null;

    return (IQueryable<IReportObject>)query.DynamicInvoke(args);
}

Использование:

var results = ExecuteQuery(
    typeof(ActivityRepository),
    "GetCompiledLatestProjects", 
    dataContext, 
    projectId);

Надеюсь, что поможет:)

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