2010-07-01 7 views
0

J'essaie de trouver et d'exécuter un CompiledQuery donné le nom. Comment accéder à la requête compilée par son nom et comment puis-je appeler le délégué?comment utiliser un délégué pour obtenir par nom un CompiledQuery

est ici aussi loin que je peux obtenir - je reçois l'erreur « Erreur de liaison pour cibler la méthode »

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); 

// Autre compilation des requêtes omises, mais les résultats sont des objets IQueryable qui mettent en œuvre une interface commune 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 
     } 
    } 
} 

Répondre

0

vous pouvez probablement faire quelque sorte de longue haleine d'essayer d'identifier les champs de type Func < ...> avec un DataContext comme premier argument que le retour IQueryable, mais vous trouverez peut-être beaucoup plus facile d'ajouter simplement un attribut personnalisé:

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

... que vous pouvez ajouter à votre champ:

[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); 

Vous pouvez ensuite sélectionner la requête sur cette base, et son nom:

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); 
} 

Utilisation:

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

Espérons que ça aide :)

+0

Excellente solution - Je n'avais pas pensé à utiliser des attributs ici, mais c'est en fait un endroit parfait pour eux. Merci de votre aide. – Andrew

+0

C'est bien si vous acceptez les réponses si vous pensez qu'ils sont utiles :) –

Questions connexes