C# 单词合并的字符串替换

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}

使用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},  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));
    }
}