2009-11-16 6 views
1

J'écris un système de gestion de contenu dans ASP.NET/C# dont le modèle du site est défini dans un fichier html. Je passe des paramètres au fichier html avec blocs. Un bloc commence par [ et se termine par ]. Un exemple pour un modèle avec quelques blocs simples:Analyse et réflexion de modèles

<html> 
<head> 
    <title>[Title]</title> 
    <meta name="description" content="[Description]" /> 
</head> 
<body> 
    <h1>[Headline]</h1> 
    <p>[Text]</p> 
</body> 
</html> 

Maintenant, j'ai une classe qui représente le modèle. La classe pour le modèle exemple ressemble à ceci:

public class MyTemplate 
{ 
    public string Title 
    { 
     get; 
     set; 
    } 

    public string Description 
    { 
     get; 
     set; 
    } 

    public string Headline 
    { 
     get; 
     set;   
    } 

    public string Text 
    { 
     get; 
     set;   
    } 
} 

La classe pourrait être une classe que je vous écris, une classe générée par LINQ to SQL ou tout simplement une classe.

J'ai créé une méthode qui remplace un bloc par la valeur de la propriété. J'utilise l'expression régulière à cette fin:

public static string ParseTemplateFromObject(string input, object obj) 
    { 
     return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match) 
     { 
      var blockName = match.Result("$1"); 

      return obj.GetType().GetProperties().SingleOrDefault(p => p.Name.Equals(blockName, StringComparison.OrdinalIgnoreCase)) 
       .GetValue(obj, null).ToString(); 

     }), RegexOptions.Multiline); 
    } 

... et cela fonctionne. J'utilise GetProperties(), puis Linq au lieu de GetProperty pour éviter la casse. Mais maintenant j'ai un autre problème, quand je veux utiliser des paramètres dans un bloc. Par exemple: Je veux créer un menu vertical. Le menu du système peut être vertical ou horizontal:

[Menu Id=1, Direction="Vertical"] 

Alors, j'ai décidé que ce type de bloc appelle une méthode et extrait sa valeur, au lieu d'extraire la valeur de sa propriété. Exemple:

public class MyTemplate 
{ 
    ... 
    public string Menu(int id, string direction) 
    { 
     string menu = ...; 
     return menu; 
    } 
} 

Je tendis ParseTemplateFromObject pour soutenir ceci:

public static string ParseTemplateFromObject(string input, object obj) 
    { 
     return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match) 
     { 
      var blockName = match.Result("$1"); 

      var m = Regex.Match(blockName, "(?<Name>\\w+)=((?<Value>\\w+)|\"(?<Value>([^\"]*))\")"); 

      if (m.Captures.Count > 0) 
      { 
       var method = obj.GetType().GetMethods().Single(p => p.Name.Equals(blockName.Substring(0, blockName.IndexOf(' ')) 
        , StringComparison.OrdinalIgnoreCase)); 

       var methodParameters = method.GetParameters(); 
       var parameters = new object[methodParameters.Length]; 

       while (m.Success) 
       { 
        var name = m.Groups["Name"].Value; 
        var value = m.Groups["Value"].Value; 

        var methodParameter = methodParameters.Single(p => p.Name.ToLower() == name.ToLower()); 
        parameters[methodParameter.Position] = 
         Convert.ChangeType(value, methodParameter.ParameterType); 

        m = m.NextMatch(); 
       } 

       return method.Invoke(obj, parameters).ToString(); 
      } 
      else 
      { 
       return obj.GetType().GetProperties().SingleOrDefault(p => p.Name.Equals(blockName, StringComparison.OrdinalIgnoreCase)) 
        .GetValue(obj, null).ToString(); 

      } 
     }), RegexOptions.Multiline); 
    } 
} 

Il travaille, mais je suis à la recherche des moyens de rendre plus efficace. Et je ne sais pas si c'est vraiment la bonne façon de mettre en œuvre cela?

Merci.

Répondre

0

Avez-vous envisagé de gérer le style des jetons dans le modèle réel plutôt que de les styliser à partir du code? Par exemple, vous avez une propriété de direction qui pourrait être un candidat idéal pour mon approche suggérée. De cette façon, vous pouvez garder l'analyse des jetons très simple.

1

Peut-être utiliser le modèle natif fourni par ASP.Net? Par exemple, définissez vos modèles à l'aide de pages .aspx standard, puis utilisez la méthode Server.Execute pour capturer les résultats générés par ces pages. Vous serez en mesure d'utiliser des blocs de code serveur (<% =%>) à 1.) Insérer des variables exposées par le code derrière ou 2.) exécuter des méthodes dans le code derrière. Vous épargnerait l'effort de mise à jour de votre code d'analyse et fournirait un format de modèle largement reconnu.

+0

cela devient un désordre lorsque vous essayez de le faire à partir d'une application de la console – Shawn