diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ExpressiveAnnotations.MvcUnobtrusive.Tests.csproj b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ExpressiveAnnotations.MvcUnobtrusive.Tests.csproj
index ae50311..7b17c93 100644
--- a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ExpressiveAnnotations.MvcUnobtrusive.Tests.csproj
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ExpressiveAnnotations.MvcUnobtrusive.Tests.csproj
@@ -68,6 +68,11 @@
+
+ True
+ True
+ Resources.resx
+
@@ -86,6 +91,13 @@
Designer
+
+
+
+ PublicResXFileCodeGenerator
+ Resources.Designer.cs
+
+
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.Designer.cs b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.Designer.cs
new file mode 100644
index 0000000..3f709c7
--- /dev/null
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.Designer.cs
@@ -0,0 +1,72 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace ExpressiveAnnotations.MvcUnobtrusive.Tests {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExpressiveAnnotations.MvcUnobtrusive.Tests.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to default.
+ ///
+ public static string Lang {
+ get {
+ return ResourceManager.GetString("Lang", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.pl.resx b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.pl.resx
new file mode 100644
index 0000000..d114000
--- /dev/null
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.pl.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ polski
+
+
\ No newline at end of file
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.resx b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.resx
new file mode 100644
index 0000000..3e13e89
--- /dev/null
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/Resources.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ default
+
+
\ No newline at end of file
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ValidatorsTest.cs b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ValidatorsTest.cs
index 84634cc..62f3e43 100644
--- a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ValidatorsTest.cs
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ValidatorsTest.cs
@@ -5,6 +5,7 @@
using System.IO;
using System.Linq;
using System.Linq.Expressions;
+using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
@@ -148,21 +149,47 @@ public void empty_client_validation_rules_are_not_created()
[TestMethod]
public void verify_formatted_message_sent_to_client()
{
- var model = new Model();
+ var model = new MsgModel();
var metadata = GetModelMetadata(model, m => m.Value);
var controllerContext = GetControllerContext();
var assert = new AssertThatValidator(metadata, controllerContext, new AssertThatAttribute("1 > 2")
{
- ErrorMessage = "{0}{1}{Value:n}{Value}{{Value}}"
+ ErrorMessage = "_{0}{1}{Value:n}{Value:N}{Value}{Value}_{{Value}}{{{Value}}}{{{{Value}}}}_"
});
var assertRule = assert.GetClientValidationRules().Single();
var map = JsonConvert.DeserializeObject((string) assertRule.ValidationParameters["errfieldsmap"]);
- var expected = "Value1 > 2_{Value}_" + map.Value + "{Value}";
+ var expected = "_Value1 > 2_{Value}__{Value}_" + map.Value + map.Value + "_{Value}" + "{" + map.Value + "}" + "{{Value}}_";
Assert.AreEqual(expected, assertRule.ErrorMessage);
}
+ [TestMethod]
+ public void verify_that_culture_change_affects_message_sent_to_client()
+ {
+ var model = new MsgModel();
+ var metadata = GetModelMetadata(model, m => m.Lang);
+ var controllerContext = GetControllerContext();
+
+ var assert = new AssertThatValidator(metadata, controllerContext,
+ new AssertThatAttribute("1 > 2") {ErrorMessage = "{Lang:n}"});
+ var assertRule = assert.GetClientValidationRules().Single();
+ Assert.AreEqual("default", assertRule.ErrorMessage);
+
+ // change culture
+ var culture = Thread.CurrentThread.CurrentUICulture;
+ Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("pl");
+
+ // simulate next request - create new validator
+ assert = new AssertThatValidator(metadata, controllerContext,
+ new AssertThatAttribute("1 > 2") {ErrorMessage = "{Lang:n}"});
+ assertRule = assert.GetClientValidationRules().Single();
+ Assert.AreEqual("polski", assertRule.ErrorMessage);
+
+ // restore culture
+ Thread.CurrentThread.CurrentUICulture = culture;
+ }
+
[TestMethod]
public void possible_naming_colission_at_client_side_are_detected()
{
@@ -257,11 +284,19 @@ public enum State
public class Model
{
- [Display(Name="_{Value}_")]
public int Value { get; set; }
[ValueParser("arrayparser")]
public int[] Array { get; set; }
public State Status { get; set; }
}
+
+ public class MsgModel
+ {
+ [Display(Name = "_{Value}_")]
+ public int Value { get; set; }
+
+ [Display(ResourceType = typeof (Resources), Name = "Lang")]
+ public string Lang { get; set; }
+ }
}
}
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive/MapCache.cs b/src/ExpressiveAnnotations.MvcUnobtrusive/MapCache.cs
index b169bd8..d1c67a9 100644
--- a/src/ExpressiveAnnotations.MvcUnobtrusive/MapCache.cs
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive/MapCache.cs
@@ -39,6 +39,5 @@ internal class CacheItem
public IDictionary ConstsMap { get; set; }
public IDictionary ParsersMap { get; set; }
public IDictionary ErrFieldsMap { get; set; }
- public string FormattedErrorMessage { get; set; }
}
}
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive/Validators/ExpressiveValidator.cs b/src/ExpressiveAnnotations.MvcUnobtrusive/Validators/ExpressiveValidator.cs
index 125d547..be6390f 100644
--- a/src/ExpressiveAnnotations.MvcUnobtrusive/Validators/ExpressiveValidator.cs
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive/Validators/ExpressiveValidator.cs
@@ -54,10 +54,6 @@ protected ExpressiveValidator(ModelMetadata metadata, ControllerContext context,
}).Where(x => x.ParserAttribute != null)
.ToDictionary(x => x.PropertyName, x => x.ParserAttribute.ParserName);
- IDictionary errFieldsMap;
- FormattedErrorMessage = attribute.FormatErrorMessage(metadata.GetDisplayName(), attribute.Expression, metadata.ContainerType, out errFieldsMap); // fields names, in contrast to values, do not change in runtime, so will be provided in message (less code in js)
- ErrFieldsMap = errFieldsMap;
-
AssertNoNamingCollisionsAtCorrespondingSegments();
attribute.Compile(metadata.ContainerType);
@@ -67,7 +63,6 @@ protected ExpressiveValidator(ModelMetadata metadata, ControllerContext context,
ConstsMap = ConstsMap,
ParsersMap = ParsersMap,
ErrFieldsMap = ErrFieldsMap,
- FormattedErrorMessage = FormattedErrorMessage
};
});
@@ -75,9 +70,12 @@ protected ExpressiveValidator(ModelMetadata metadata, ControllerContext context,
ConstsMap = item.ConstsMap;
ParsersMap = item.ParsersMap;
ErrFieldsMap = item.ErrFieldsMap;
- FormattedErrorMessage = item.FormattedErrorMessage;
Expression = attribute.Expression;
+
+ IDictionary errFieldsMap;
+ FormattedErrorMessage = attribute.FormatErrorMessage(metadata.GetDisplayName(), attribute.Expression, metadata.ContainerType, out errFieldsMap); // fields names, in contrast to values, do not change in runtime, so will be provided in message (less code in js)
+ ErrFieldsMap = errFieldsMap;
}
catch (Exception e)
{
diff --git a/src/ExpressiveAnnotations.MvcWebSample/Resources.Designer.cs b/src/ExpressiveAnnotations.MvcWebSample/Resources.Designer.cs
index 783e562..92e2223 100644
--- a/src/ExpressiveAnnotations.MvcWebSample/Resources.Designer.cs
+++ b/src/ExpressiveAnnotations.MvcWebSample/Resources.Designer.cs
@@ -502,7 +502,7 @@ public static string ReasonForTravelRequired {
}
///
- /// Looks up a localized string similar to If you are under 18 (indicated {Age} in {Age:N} field, yes {Age}), give us a reason of your travel no matter where you go (BTW. {Country}... nice choice)..
+ /// Looks up a localized string similar to If you are under 18 (indicated {Age} in {Age:N} field, yes - {Age:N} {Age}), give us a reason of your travel no matter where you go (BTW. {Country}... nice choice)..
///
public static string ReasonForTravelRequiredForYouth {
get {
diff --git a/src/ExpressiveAnnotations.MvcWebSample/Resources.pl.resx b/src/ExpressiveAnnotations.MvcWebSample/Resources.pl.resx
index 821937e..aed180e 100644
--- a/src/ExpressiveAnnotations.MvcWebSample/Resources.pl.resx
+++ b/src/ExpressiveAnnotations.MvcWebSample/Resources.pl.resx
@@ -265,7 +265,7 @@
Jeśli planujesz wyjechać za granicę i jesteś w wieku 25-55 lat lub planujesz odwiedzić dwukrotnie ten sam obcy kraj, podaj powody.
- Jeśli planujesz jakąkolwiek podróż i nie masz ukończonych 18 lat (wskazałeś w polu {Age:N} wartość {Age}, tak {Age}), podaj powody (PS. {Country}... dobry wybór).
+ Jeśli planujesz jakąkolwiek podróż i nie masz ukończonych 18 lat (wskazałeś w polu {Age:N} wartość {Age}, tak - {Age:N} {Age}), podaj powody (PS. {Country}... dobry wybór).
Data powrotu
diff --git a/src/ExpressiveAnnotations.MvcWebSample/Resources.resx b/src/ExpressiveAnnotations.MvcWebSample/Resources.resx
index 191b6e4..140dc57 100644
--- a/src/ExpressiveAnnotations.MvcWebSample/Resources.resx
+++ b/src/ExpressiveAnnotations.MvcWebSample/Resources.resx
@@ -265,7 +265,7 @@
If you plan to go abroad and you are between 25 and 55 or plan to visit the same foreign country twice, write down your reasons.
- If you are under 18 (indicated {Age} in {Age:N} field, yes {Age}), give us a reason of your travel no matter where you go (BTW. {Country}... nice choice).
+ If you are under 18 (indicated {Age} in {Age:N} field, yes - {Age:N} {Age}), give us a reason of your travel no matter where you go (BTW. {Country}... nice choice).
Return date
diff --git a/src/ExpressiveAnnotations.Tests/AttribsTest.cs b/src/ExpressiveAnnotations.Tests/AttribsTest.cs
index 3666cd9..8be4044 100644
--- a/src/ExpressiveAnnotations.Tests/AttribsTest.cs
+++ b/src/ExpressiveAnnotations.Tests/AttribsTest.cs
@@ -2,8 +2,10 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
+using System.Globalization;
using System.Linq;
using System.Reflection;
+using System.Threading;
using ExpressiveAnnotations.Attributes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -168,6 +170,21 @@ public void verify_custom_error_message_after_validation()
});
}
+ [TestMethod]
+ public void verify_that_culture_change_affects_validation_message()
+ {
+ AssertErrorMessage("{Lang:n}", "default", "default");
+
+ // change culture
+ var culture = Thread.CurrentThread.CurrentUICulture;
+ Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("pl");
+
+ AssertErrorMessage("{Lang:n}", "polski", "polski");
+
+ // restore culture
+ Thread.CurrentThread.CurrentUICulture = culture;
+ }
+
private static void AssertErrorMessage(string input, string assertThatOutput, string requiredIfOutput)
{
var assertThat = new AssertThatAttribute("1!=1");
@@ -237,10 +254,14 @@ private class MsgModel
{
[DisplayAttribute(Name = "_{Value1}_")]
public int Value1 { get; set; }
- [DisplayAttribute(ResourceType = typeof(Resources), Name = "Value2")]
+
+ [DisplayAttribute(ResourceType = typeof (Resources), Name = "Value2")]
public int Value2 { get; set; }
public MsgModel Internal { get; set; }
+
+ [Display(ResourceType = typeof (Resources), Name = "Lang")]
+ public string Lang { get; set; }
}
}
diff --git a/src/ExpressiveAnnotations.Tests/ExpressiveAnnotations.Tests.csproj b/src/ExpressiveAnnotations.Tests/ExpressiveAnnotations.Tests.csproj
index 245aef9..44cfe07 100644
--- a/src/ExpressiveAnnotations.Tests/ExpressiveAnnotations.Tests.csproj
+++ b/src/ExpressiveAnnotations.Tests/ExpressiveAnnotations.Tests.csproj
@@ -78,6 +78,7 @@
+
PublicResXFileCodeGenerator
Resources.Designer.cs
diff --git a/src/ExpressiveAnnotations.Tests/Resources.Designer.cs b/src/ExpressiveAnnotations.Tests/Resources.Designer.cs
index 77ded0c..71d93d4 100644
--- a/src/ExpressiveAnnotations.Tests/Resources.Designer.cs
+++ b/src/ExpressiveAnnotations.Tests/Resources.Designer.cs
@@ -60,6 +60,15 @@ internal Resources() {
}
}
+ ///
+ /// Looks up a localized string similar to default.
+ ///
+ public static string Lang {
+ get {
+ return ResourceManager.GetString("Lang", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to _{Value2}_.
///
diff --git a/src/ExpressiveAnnotations.Tests/Resources.pl.resx b/src/ExpressiveAnnotations.Tests/Resources.pl.resx
new file mode 100644
index 0000000..d114000
--- /dev/null
+++ b/src/ExpressiveAnnotations.Tests/Resources.pl.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ polski
+
+
\ No newline at end of file
diff --git a/src/ExpressiveAnnotations.Tests/Resources.resx b/src/ExpressiveAnnotations.Tests/Resources.resx
index 195b3bc..0b35630 100644
--- a/src/ExpressiveAnnotations.Tests/Resources.resx
+++ b/src/ExpressiveAnnotations.Tests/Resources.resx
@@ -117,6 +117,9 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ default
+
_{Value2}_
diff --git a/src/ExpressiveAnnotations/Attributes/ExpressiveAttribute.cs b/src/ExpressiveAnnotations/Attributes/ExpressiveAttribute.cs
index 600cc39..82dad3a 100644
--- a/src/ExpressiveAnnotations/Attributes/ExpressiveAttribute.cs
+++ b/src/ExpressiveAnnotations/Attributes/ExpressiveAttribute.cs
@@ -177,8 +177,8 @@ public string FormatErrorMessage(string displayName, string expression, object o
IList items;
var message = PreformatMessage(displayName, expression, out items);
- message = items.Aggregate(message, (cargo, current) => current.Indicator != null && !current.Constant ? cargo.Replace(current.Id.ToString(), Helper.ExtractDisplayName(objectInstance.GetType(), current.FieldPath)) : cargo);
- message = items.Aggregate(message, (cargo, current) => current.Indicator == null && !current.Constant ? cargo.Replace(current.Id.ToString(), (Helper.ExtractValue(objectInstance, current.FieldPath) ?? string.Empty).ToString()) : cargo);
+ message = items.Aggregate(message, (cargo, current) => current.Indicator != null && !current.Constant ? cargo.Replace(current.Uuid.ToString(), Helper.ExtractDisplayName(objectInstance.GetType(), current.FieldPath)) : cargo);
+ message = items.Aggregate(message, (cargo, current) => current.Indicator == null && !current.Constant ? cargo.Replace(current.Uuid.ToString(), (Helper.ExtractValue(objectInstance, current.FieldPath) ?? string.Empty).ToString()) : cargo);
return message;
}
@@ -201,8 +201,10 @@ public string FormatErrorMessage(string displayName, string expression, Type obj
IList items;
var message = PreformatMessage(displayName, expression, out items);
- fieldsMap = items.Where(x => x.Indicator == null && !x.Constant).ToDictionary(x => x.FieldPath, x => x.Id);
- message = items.Aggregate(message, (cargo, current) => current.Indicator != null && !current.Constant ? cargo.Replace(current.Id.ToString(), Helper.ExtractDisplayName(objectType, current.FieldPath)) : cargo);
+ var map = items.Where(x => x.Indicator == null && !x.Constant).Select(x => x.FieldPath).Distinct().ToDictionary(x => x, x => Guid.NewGuid()); // sanitize
+ message = items.Aggregate(message, (cargo, current) => current.Indicator != null && !current.Constant ? cargo.Replace(current.Uuid.ToString(), Helper.ExtractDisplayName(objectType, current.FieldPath)) : cargo);
+ message = items.Aggregate(message, (cargo, current) => current.Indicator == null && !current.Constant ? cargo.Replace(current.Uuid.ToString(), map[current.FieldPath].ToString()) : cargo);
+ fieldsMap = map;
return message;
}
@@ -264,7 +266,7 @@ private string PreformatMessage(string displayName, string expression, out IList
{
var message = MessageFormatter.FormatString(ErrorMessageString, out items); // process custom format items: {fieldPath[:indicator]}, and substitute them entirely with guids, not to interfere with standard string.Format() invoked below
message = string.Format(message, displayName, expression); // process standard format items: {index[,alignment][:formatString]}, https://msdn.microsoft.com/en-us/library/txafckwd(v=vs.110).aspx
- message = items.Aggregate(message, (cargo, current) => cargo.Replace(current.Id.ToString(), current.Substitute)); // give back, initially preprocessed, custom format items
+ message = items.Aggregate(message, (cargo, current) => cargo.Replace(current.Uuid.ToString(), current.Substitute)); // give back, initially preprocessed, custom format items
return message;
}
}
diff --git a/src/ExpressiveAnnotations/MessageFormatter.cs b/src/ExpressiveAnnotations/MessageFormatter.cs
index ca07524..60823cf 100644
--- a/src/ExpressiveAnnotations/MessageFormatter.cs
+++ b/src/ExpressiveAnnotations/MessageFormatter.cs
@@ -24,7 +24,7 @@ public static string FormatString(string input, out IList items)
for (var i = 0; i < matches.Count; i++)
{
var match = matches[i];
- var arg = match.Value;
+ var item = match.Value;
var leftBraces = match.Groups[1];
var rightBraces = match.Groups[2];
@@ -36,8 +36,12 @@ public static string FormatString(string input, out IList items)
message.Append(input.Substring(start, chars));
prev = match;
- if (items.Any(x => x.Body == arg))
+ var added = items.SingleOrDefault(x => x.Body == item);
+ if (added != null)
+ {
+ message.Append(added.Uuid);
continue;
+ }
var length = leftBraces.Length;
@@ -45,28 +49,31 @@ public static string FormatString(string input, out IList items)
var leftBracesFlattened = new string('{', length / 2);
var rightBracesFlattened = new string('}', length / 2);
- var guid = Guid.NewGuid();
-
- var param = arg.Substring(length, arg.Length - 2 * length);
- items.Add(new FormatItem
+ var uuid = Guid.NewGuid();
+ var param = item.Substring(length, item.Length - 2 * length);
+ var current = new FormatItem
{
- Id = guid,
- Body = arg,
+ Uuid = uuid,
+ Body = item,
Constant = length % 2 == 0,
FieldPath = param.Contains(":") ? param.Substring(0, param.IndexOf(":", StringComparison.Ordinal)) : param,
Indicator = param.Contains(":") ? param.Substring(param.IndexOf(":", StringComparison.Ordinal) + 1) : null,
- Substitute = string.Format("{0}{1}{2}", leftBracesFlattened, length % 2 != 0 ? guid.ToString() : param, rightBracesFlattened) // for odd number of braces, substitute param with respective value (just like string.Format() does)
- });
- message.Append(guid);
+ Substitute = string.Format("{0}{1}{2}", leftBracesFlattened, length % 2 != 0 ? uuid.ToString() : param, rightBracesFlattened) // for odd number of braces, substitute param with respective value (just like string.Format() does)
+ };
+ items.Add(current);
+ message.Append(current.Uuid);
}
+ if(prev != null)
+ message.Append(input.Substring(prev.Index + prev.Length));
+
return message.Length > 0 ? message.ToString() : input;
}
}
internal class FormatItem
{
- public Guid Id { get; set; }
+ public Guid Uuid { get; set; }
public string Body { get; set; }
public bool Constant { get; set; }
public string FieldPath { get; set; }