C# 单词合并的字符串替换
使用asp.NET4 我们在工作中做了很多单词合并。我希望嵌入自己的语法,而不是使用Word的复杂条件语句。比如:C# 单词合并的字符串替换,c#,asp.net,sql,ms-word,C#,Asp.net,Sql,Ms Word,使用asp.NET4 我们在工作中做了很多单词合并。我希望嵌入自己的语法,而不是使用Word的复杂条件语句。比如: Dear Mr. { select lastname from users where userid = 7 }, Your invoice for this quarter is: ${ select amount from invoices where userid = 7 }. ...... 理想情况下,我想把它变成: string.Format("Dear Mr. {0}
Dear Mr. { select lastname from users where userid = 7 },
Your invoice for this quarter is: ${ select amount from invoices where userid = 7 }.
......
理想情况下,我想把它变成:
string.Format("Dear Mr. {0}, Your invoice for this quarter is: ${1}", sqlEval[0], sqlEval[1]);
有什么想法吗?好吧,我并不建议您为此推出自己的解决方案,但是我会回答您提出的问题 首先,您需要处理文本并提取SQL语句。为此,您需要一个简单的解析器:
/// <summary>Parses the input string and extracts a unique list of all placeholders.</summary>
/// <remarks>
/// This method does not handle escaping of delimiters
/// </remarks>
public static IList<string> Parse(string input)
{
const char placeholderDelimStart = '{';
const char placeholderDelimEnd = '}';
var characters = input.ToCharArray();
var placeHolders = new List<string>();
string currentPlaceHolder = string.Empty;
bool inPlaceHolder = false;
for (int i = 0; i < characters.Length; i++)
{
var currentChar = characters[i];
// Start of a placeholder
if (!inPlaceHolder && currentChar == placeholderDelimStart)
{
currentPlaceHolder = string.Empty;
inPlaceHolder = true;
continue;
}
// Start of a placeholder when we already have one
if (inPlaceHolder && currentChar == placeholderDelimStart)
throw new InvalidOperationException("Unexpected character detected at position " + i);
// We found the end marker while in a placeholder - we're done with this placeholder
if (inPlaceHolder && currentChar == placeholderDelimEnd)
{
if (!placeHolders.Contains(currentPlaceHolder))
placeHolders.Add(currentPlaceHolder);
inPlaceHolder = false;
continue;
}
// End of a placeholder with no matching start
if (!inPlaceHolder && currentChar == placeholderDelimEnd)
throw new InvalidOperationException("Unexpected character detected at position " + i);
if (inPlaceHolder)
currentPlaceHolder += currentChar;
}
return placeHolders;
}
这显然不是最有效的方法,但我认为它充分证明了这一概念,同时又不会弄脏水
您需要定义
Evaluate(string)
方法。这将处理SQL的执行。我刚刚为这里的一家律师事务所构建了这样一个专有的解决方案。
我评估了一个叫做Windward reports的产品。这有点贵,尤其是如果你需要大量的拷贝,但是对于一个用户来说这并不坏
它可以从XML或SQL数据源(或者更多,如果我记得的话)
可能值得一看(不,我不是为他们工作,只是评估了他们的东西)你可能想看看codeplex上的razor引擎项目 在模板中使用SQL等看起来不是个好主意。我建议您为每个模板创建一个ViewModel 剃须刀真的很好用。只需添加一个引用,导入名称空间,然后调用Parse方法,如下所示: (请原谅语法!)
您的字符串可以来自任何地方-我将其与存储在数据库中的模板一起使用,您可以从文件或其他任何地方加载它。作为一个视图引擎,它非常强大,你可以做有条件的事情、循环等等。我最终推出了自己的解决方案,但谢谢。我真的不喜欢if语句。我需要把它们重构出来。这是:
var mailingMergeString = new MailingMergeString(input);
var output = mailingMergeString.ParseMailingMergeString();
public class MailingMergeString
{
private string _input;
public MailingMergeString(string input)
{
_input = input;
}
public string ParseMailingMergeString()
{
IList<SqlReplaceCommand> sqlCommands = new List<SqlReplaceCommand>();
var i = 0;
const string openBrace = "{";
const string closeBrace = "}";
while (string.IsNullOrWhiteSpace(_input) == false)
{
var sqlReplaceCommand = new SqlReplaceCommand();
var open = _input.IndexOf(openBrace) + 1;
var close = _input.IndexOf(closeBrace);
var length = close != -1 ? close - open : _input.Length;
var newInput = _input.Substring(close + 1);
var nextClose = newInput.Contains(openBrace) ? newInput.IndexOf(openBrace) : newInput.Length;
if (i == 0 && open > 0)
{
sqlReplaceCommand.Text = _input.Substring(0, open - 1);
_input = _input.Substring(open - 1);
}
else
{
sqlReplaceCommand.Command = _input.Substring(open, length);
sqlReplaceCommand.PlaceHolder = openBrace + i + closeBrace;
sqlReplaceCommand.Text = _input.Substring(close + 1, nextClose);
sqlReplaceCommand.NewInput = _input.Substring(close + 1);
_input = newInput.Contains(openBrace) ? sqlReplaceCommand.NewInput : string.Empty;
}
sqlCommands.Add(sqlReplaceCommand);
i++;
}
return sqlCommands.GetParsedString();
}
internal class SqlReplaceCommand
{
public string Command { get; set; }
public string SqlResult { get; set; }
public string PlaceHolder { get; set; }
public string Text { get; set; }
protected internal string NewInput { get; set; }
}
}
internal static class SqlReplaceExtensions
{
public static string GetParsedString(this IEnumerable<MailingMergeString.SqlReplaceCommand> sqlCommands)
{
return sqlCommands.Aggregate("", (current, replaceCommand) => current + (replaceCommand.PlaceHolder + replaceCommand.Text));
}
}
var mailingMergeString=新的mailingMergeString(输入);
var output=mailingMergeString.ParseMailingMergeString();
公共类MailingMergeString
{
私有字符串输入;
publicmailingmergestring(字符串输入)
{
_输入=输入;
}
公共字符串ParseMailingMergeString()
{
IList sqlCommands=new List();
var i=0;
常量字符串openBrace=“{”;
常量字符串closeBrace=“}”;
while(string.IsNullOrWhiteSpace(_input)==false)
{
var sqlReplaceCommand=新的sqlReplaceCommand();
var open=_input.IndexOf(openBrace)+1;
var close=_input.IndexOf(closeBrace);
变量长度=关闭!=-1?关闭-打开:_input.length;
var newInput=_input.Substring(close+1);
var nextClose=newInput.Contains(openBrace)?newInput.IndexOf(openBrace):newInput.Length;
如果(i==0&&open>0)
{
sqlReplaceCommand.Text=\u input.Substring(0,open-1);
_input=\u input.Substring(open-1);
}
其他的
{
sqlReplaceCommand.Command=\u input.Substring(open,length);
sqlReplaceCommand.PlaceHolder=openBrace+i+closeBrace;
sqlReplaceCommand.Text=\u input.Substring(close+1,nextClose);
sqlReplaceCommand.NewInput=\u input.Substring(close+1);
_input=newInput.Contains(openBrace)?sqlReplaceCommand.newInput:string.Empty;
}
添加(sqlReplaceCommand);
i++;
}
返回sqlCommands.GetParsedString();
}
内部类SqlReplaceCommand
{
公共字符串命令{get;set;}
公共字符串SqlResult{get;set;}
公共字符串占位符{get;set;}
公共字符串文本{get;set;}
受保护的内部字符串NewInput{get;set;}
}
}
内部静态类SqlReplaceExtensions
{
公共静态字符串GetParsedString(此IEnumerable sqlCommands)
{
返回sqlCommands.Aggregate(“,(current,replaceCommand)=>current+(replaceCommand.PlaceHolder+replaceCommand.Text));
}
}
更大的图景/背景是什么?您真的想在查询中包含实际的ID号吗?string.Format()
的要点在于,您将数据与其所使用的字符串表示形式分开-为什么要将它们重新合并在一起?而不知道要合并的Word文档是如何生成的(即谁有权访问它们)我不得不说,允许任意SQL被评估或执行似乎很危险。。SQL注入潜伏在那些弯曲的大括号之间。这是一个内部应用程序。sql注入并不重要。我需要在文档中计算sql。什么是简单语法?我如何评估它?
MyViewModel myModel = new MyViewModel("Bob",150.00); //set properties
string myTemplate = "Dear Mr. @Model.FirstName, Your invoice for this quarter is: @Model.InvoiceAmount";
string myOutput = Razor.Parse(myTemplate, myModel);
var mailingMergeString = new MailingMergeString(input);
var output = mailingMergeString.ParseMailingMergeString();
public class MailingMergeString
{
private string _input;
public MailingMergeString(string input)
{
_input = input;
}
public string ParseMailingMergeString()
{
IList<SqlReplaceCommand> sqlCommands = new List<SqlReplaceCommand>();
var i = 0;
const string openBrace = "{";
const string closeBrace = "}";
while (string.IsNullOrWhiteSpace(_input) == false)
{
var sqlReplaceCommand = new SqlReplaceCommand();
var open = _input.IndexOf(openBrace) + 1;
var close = _input.IndexOf(closeBrace);
var length = close != -1 ? close - open : _input.Length;
var newInput = _input.Substring(close + 1);
var nextClose = newInput.Contains(openBrace) ? newInput.IndexOf(openBrace) : newInput.Length;
if (i == 0 && open > 0)
{
sqlReplaceCommand.Text = _input.Substring(0, open - 1);
_input = _input.Substring(open - 1);
}
else
{
sqlReplaceCommand.Command = _input.Substring(open, length);
sqlReplaceCommand.PlaceHolder = openBrace + i + closeBrace;
sqlReplaceCommand.Text = _input.Substring(close + 1, nextClose);
sqlReplaceCommand.NewInput = _input.Substring(close + 1);
_input = newInput.Contains(openBrace) ? sqlReplaceCommand.NewInput : string.Empty;
}
sqlCommands.Add(sqlReplaceCommand);
i++;
}
return sqlCommands.GetParsedString();
}
internal class SqlReplaceCommand
{
public string Command { get; set; }
public string SqlResult { get; set; }
public string PlaceHolder { get; set; }
public string Text { get; set; }
protected internal string NewInput { get; set; }
}
}
internal static class SqlReplaceExtensions
{
public static string GetParsedString(this IEnumerable<MailingMergeString.SqlReplaceCommand> sqlCommands)
{
return sqlCommands.Aggregate("", (current, replaceCommand) => current + (replaceCommand.PlaceHolder + replaceCommand.Text));
}
}