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.
cela devient un désordre lorsque vous essayez de le faire à partir d'une application de la console – Shawn