Simple Uri parser and DTO
up vote
0
down vote
favorite
I needed some data structure for holding Uris so I thought I try the Uri
class. It quickly turned out that it's very impractical because:
- it's missing an implicit cast from/to string
- it doesn't automatically recognize uris as absolute or relative without specifying the
UriKind
- it doesn't parse the query-string so it cannot compare uris reliably when key-value pairs are in different order
- it's not easy to combine an absolute uri with a relative one
Working with it is just too inconvenient. As a solution I created my own SimpleUri
that should solve these issues. It doesn't support everything yet because I don't need it right now but adding a couple of more regexes later should be a problem.
public class SimpleUri : IEquatable<SimpleUri>, IEquatable<string>
{
// https://regex101.com/r/sd288W/1
// using 'new' for _nicer_ syntax
private static readonly string UriPattern = string.Join(string.Empty, new
{
/* language=regexp */ @"^(?:(?<scheme>w+):)?",
/* language=regexp */ @"(?://(?<authority>w+))?",
/* language=regexp */ @"(?<path>[a-z0-9/:]+)",
/* language=regexp */ @"(?:?(?<query>[a-z0-9=&]+))?",
/* language=regexp */ @"(?:#(?<fragment>[a-z0-9]+))?"
});
public static readonly IEqualityComparer<SimpleUri> Comparer = EqualityComparerFactory<SimpleUri>.Create
(
equals: (x, y) => StringComparer.OrdinalIgnoreCase.Equals(x, y),
getHashCode: (obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj)
);
public SimpleUri([NotNull] string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));
var uriMatch = Regex.Match
(
uri,
UriPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
);
if (!uriMatch.Success)
{
throw new ArgumentException(paramName: nameof(uri), message: $"'{uri}' is not a valid Uri.");
}
Scheme = uriMatch.Groups["scheme"];
Authority = uriMatch.Groups["authority"];
Path = uriMatch.Groups["path"];
Query =
uriMatch.Groups["query"].Success
? Regex
.Matches
(
uriMatch.Groups["query"].Value,
@"(?:^|&)(?<key>[a-z0-9]+)(?:=(?<value>[a-z0-9]+))?",
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
)
.Cast<Match>()
.ToImmutableDictionary
(
m => (ImplicitString)m.Groups["key"],
m => (ImplicitString)m.Groups["value"]
)
: ImmutableDictionary<ImplicitString, ImplicitString>.Empty;
Fragment = uriMatch.Groups["fragment"];
}
public SimpleUri(SimpleUri absoluteUri, SimpleUri relativeUri)
{
if (absoluteUri.IsRelative) throw new ArgumentException($"{nameof(absoluteUri)} must be an absolute Uri.");
if (!relativeUri.IsRelative) throw new ArgumentException($"{nameof(relativeUri)} must be a relative Uri.");
Scheme = absoluteUri.Scheme;
Authority = absoluteUri.Authority;
Path = absoluteUri.Path.Value.TrimEnd('/') + "/" + relativeUri.Path.Value.TrimStart('/');
Query = absoluteUri.Query;
Fragment = absoluteUri.Fragment;
}
public ImplicitString Scheme { get; }
public ImplicitString Authority { get; }
public ImplicitString Path { get; }
public IImmutableDictionary<ImplicitString, ImplicitString> Query { get; }
public ImplicitString Fragment { get; }
public bool IsRelative => !Scheme;
public override string ToString() => string.Join(string.Empty, GetComponents());
private IEnumerable<string> GetComponents()
{
if (Scheme)
{
yield return $"{Scheme}:";
}
if (Authority)
{
yield return $"//{Authority}";
}
yield return Path;
if (Query.Any())
{
var queryPairs =
Query
.OrderBy(x => (string)x.Key, StringComparer.OrdinalIgnoreCase)
.Select(x => $"{x.Key}{(x.Value ? "=" : string.Empty)}{x.Value}");
yield return $"?{string.Join("&", queryPairs)}";
}
if (Fragment)
{
yield return $"#{Fragment}";
}
}
#region IEquatable
public bool Equals(SimpleUri other) => Comparer.Equals(this, other);
public bool Equals(string other) => Comparer.Equals(this, other);
public override bool Equals(object obj) => obj is SimpleUri uri && Equals(uri);
public override int GetHashCode() => Comparer.GetHashCode(this);
#endregion
#region operators
public static implicit operator SimpleUri(string uri) => new SimpleUri(uri);
public static implicit operator string(SimpleUri uri) => uri.ToString();
public static SimpleUri operator +(SimpleUri absoluteUri, SimpleUri relativeUri) => new SimpleUri(absoluteUri, relativeUri);
#endregion
}
In this experiment I use a new helper for the first time which is the ImplicitString
. Its purpose is to be able to use a string
as a conditional without having to write any of the string.IsX
all over the place.
public class ImplicitString
{
public ImplicitString(string value) => Value = value;
public string Value { get; }
public override string ToString() => Value;
public static implicit operator ImplicitString(string value) => new ImplicitString(value);
public static implicit operator ImplicitString(Group group) => group.Value;
public static implicit operator string(ImplicitString value) => value.ToString();
public static implicit operator bool(ImplicitString value) => !string.IsNullOrWhiteSpace(value);
}
Example
I tested it with use-cases I currently need it for and it works fine:
new SimpleUri("scheme://authority/p/a/t/h?query#fragment").Dump();
new SimpleUri("scheme:p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h").Dump();
new SimpleUri("file:c:/p/a/t/h").Dump();
What do you say? Is this an optimal implementation or can it be improved?
c# parsing regex dto
add a comment |
up vote
0
down vote
favorite
I needed some data structure for holding Uris so I thought I try the Uri
class. It quickly turned out that it's very impractical because:
- it's missing an implicit cast from/to string
- it doesn't automatically recognize uris as absolute or relative without specifying the
UriKind
- it doesn't parse the query-string so it cannot compare uris reliably when key-value pairs are in different order
- it's not easy to combine an absolute uri with a relative one
Working with it is just too inconvenient. As a solution I created my own SimpleUri
that should solve these issues. It doesn't support everything yet because I don't need it right now but adding a couple of more regexes later should be a problem.
public class SimpleUri : IEquatable<SimpleUri>, IEquatable<string>
{
// https://regex101.com/r/sd288W/1
// using 'new' for _nicer_ syntax
private static readonly string UriPattern = string.Join(string.Empty, new
{
/* language=regexp */ @"^(?:(?<scheme>w+):)?",
/* language=regexp */ @"(?://(?<authority>w+))?",
/* language=regexp */ @"(?<path>[a-z0-9/:]+)",
/* language=regexp */ @"(?:?(?<query>[a-z0-9=&]+))?",
/* language=regexp */ @"(?:#(?<fragment>[a-z0-9]+))?"
});
public static readonly IEqualityComparer<SimpleUri> Comparer = EqualityComparerFactory<SimpleUri>.Create
(
equals: (x, y) => StringComparer.OrdinalIgnoreCase.Equals(x, y),
getHashCode: (obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj)
);
public SimpleUri([NotNull] string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));
var uriMatch = Regex.Match
(
uri,
UriPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
);
if (!uriMatch.Success)
{
throw new ArgumentException(paramName: nameof(uri), message: $"'{uri}' is not a valid Uri.");
}
Scheme = uriMatch.Groups["scheme"];
Authority = uriMatch.Groups["authority"];
Path = uriMatch.Groups["path"];
Query =
uriMatch.Groups["query"].Success
? Regex
.Matches
(
uriMatch.Groups["query"].Value,
@"(?:^|&)(?<key>[a-z0-9]+)(?:=(?<value>[a-z0-9]+))?",
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
)
.Cast<Match>()
.ToImmutableDictionary
(
m => (ImplicitString)m.Groups["key"],
m => (ImplicitString)m.Groups["value"]
)
: ImmutableDictionary<ImplicitString, ImplicitString>.Empty;
Fragment = uriMatch.Groups["fragment"];
}
public SimpleUri(SimpleUri absoluteUri, SimpleUri relativeUri)
{
if (absoluteUri.IsRelative) throw new ArgumentException($"{nameof(absoluteUri)} must be an absolute Uri.");
if (!relativeUri.IsRelative) throw new ArgumentException($"{nameof(relativeUri)} must be a relative Uri.");
Scheme = absoluteUri.Scheme;
Authority = absoluteUri.Authority;
Path = absoluteUri.Path.Value.TrimEnd('/') + "/" + relativeUri.Path.Value.TrimStart('/');
Query = absoluteUri.Query;
Fragment = absoluteUri.Fragment;
}
public ImplicitString Scheme { get; }
public ImplicitString Authority { get; }
public ImplicitString Path { get; }
public IImmutableDictionary<ImplicitString, ImplicitString> Query { get; }
public ImplicitString Fragment { get; }
public bool IsRelative => !Scheme;
public override string ToString() => string.Join(string.Empty, GetComponents());
private IEnumerable<string> GetComponents()
{
if (Scheme)
{
yield return $"{Scheme}:";
}
if (Authority)
{
yield return $"//{Authority}";
}
yield return Path;
if (Query.Any())
{
var queryPairs =
Query
.OrderBy(x => (string)x.Key, StringComparer.OrdinalIgnoreCase)
.Select(x => $"{x.Key}{(x.Value ? "=" : string.Empty)}{x.Value}");
yield return $"?{string.Join("&", queryPairs)}";
}
if (Fragment)
{
yield return $"#{Fragment}";
}
}
#region IEquatable
public bool Equals(SimpleUri other) => Comparer.Equals(this, other);
public bool Equals(string other) => Comparer.Equals(this, other);
public override bool Equals(object obj) => obj is SimpleUri uri && Equals(uri);
public override int GetHashCode() => Comparer.GetHashCode(this);
#endregion
#region operators
public static implicit operator SimpleUri(string uri) => new SimpleUri(uri);
public static implicit operator string(SimpleUri uri) => uri.ToString();
public static SimpleUri operator +(SimpleUri absoluteUri, SimpleUri relativeUri) => new SimpleUri(absoluteUri, relativeUri);
#endregion
}
In this experiment I use a new helper for the first time which is the ImplicitString
. Its purpose is to be able to use a string
as a conditional without having to write any of the string.IsX
all over the place.
public class ImplicitString
{
public ImplicitString(string value) => Value = value;
public string Value { get; }
public override string ToString() => Value;
public static implicit operator ImplicitString(string value) => new ImplicitString(value);
public static implicit operator ImplicitString(Group group) => group.Value;
public static implicit operator string(ImplicitString value) => value.ToString();
public static implicit operator bool(ImplicitString value) => !string.IsNullOrWhiteSpace(value);
}
Example
I tested it with use-cases I currently need it for and it works fine:
new SimpleUri("scheme://authority/p/a/t/h?query#fragment").Dump();
new SimpleUri("scheme:p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h").Dump();
new SimpleUri("file:c:/p/a/t/h").Dump();
What do you say? Is this an optimal implementation or can it be improved?
c# parsing regex dto
TheEqualityComparerFactory
can be found here.
– t3chb0t
1 hour ago
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I needed some data structure for holding Uris so I thought I try the Uri
class. It quickly turned out that it's very impractical because:
- it's missing an implicit cast from/to string
- it doesn't automatically recognize uris as absolute or relative without specifying the
UriKind
- it doesn't parse the query-string so it cannot compare uris reliably when key-value pairs are in different order
- it's not easy to combine an absolute uri with a relative one
Working with it is just too inconvenient. As a solution I created my own SimpleUri
that should solve these issues. It doesn't support everything yet because I don't need it right now but adding a couple of more regexes later should be a problem.
public class SimpleUri : IEquatable<SimpleUri>, IEquatable<string>
{
// https://regex101.com/r/sd288W/1
// using 'new' for _nicer_ syntax
private static readonly string UriPattern = string.Join(string.Empty, new
{
/* language=regexp */ @"^(?:(?<scheme>w+):)?",
/* language=regexp */ @"(?://(?<authority>w+))?",
/* language=regexp */ @"(?<path>[a-z0-9/:]+)",
/* language=regexp */ @"(?:?(?<query>[a-z0-9=&]+))?",
/* language=regexp */ @"(?:#(?<fragment>[a-z0-9]+))?"
});
public static readonly IEqualityComparer<SimpleUri> Comparer = EqualityComparerFactory<SimpleUri>.Create
(
equals: (x, y) => StringComparer.OrdinalIgnoreCase.Equals(x, y),
getHashCode: (obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj)
);
public SimpleUri([NotNull] string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));
var uriMatch = Regex.Match
(
uri,
UriPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
);
if (!uriMatch.Success)
{
throw new ArgumentException(paramName: nameof(uri), message: $"'{uri}' is not a valid Uri.");
}
Scheme = uriMatch.Groups["scheme"];
Authority = uriMatch.Groups["authority"];
Path = uriMatch.Groups["path"];
Query =
uriMatch.Groups["query"].Success
? Regex
.Matches
(
uriMatch.Groups["query"].Value,
@"(?:^|&)(?<key>[a-z0-9]+)(?:=(?<value>[a-z0-9]+))?",
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
)
.Cast<Match>()
.ToImmutableDictionary
(
m => (ImplicitString)m.Groups["key"],
m => (ImplicitString)m.Groups["value"]
)
: ImmutableDictionary<ImplicitString, ImplicitString>.Empty;
Fragment = uriMatch.Groups["fragment"];
}
public SimpleUri(SimpleUri absoluteUri, SimpleUri relativeUri)
{
if (absoluteUri.IsRelative) throw new ArgumentException($"{nameof(absoluteUri)} must be an absolute Uri.");
if (!relativeUri.IsRelative) throw new ArgumentException($"{nameof(relativeUri)} must be a relative Uri.");
Scheme = absoluteUri.Scheme;
Authority = absoluteUri.Authority;
Path = absoluteUri.Path.Value.TrimEnd('/') + "/" + relativeUri.Path.Value.TrimStart('/');
Query = absoluteUri.Query;
Fragment = absoluteUri.Fragment;
}
public ImplicitString Scheme { get; }
public ImplicitString Authority { get; }
public ImplicitString Path { get; }
public IImmutableDictionary<ImplicitString, ImplicitString> Query { get; }
public ImplicitString Fragment { get; }
public bool IsRelative => !Scheme;
public override string ToString() => string.Join(string.Empty, GetComponents());
private IEnumerable<string> GetComponents()
{
if (Scheme)
{
yield return $"{Scheme}:";
}
if (Authority)
{
yield return $"//{Authority}";
}
yield return Path;
if (Query.Any())
{
var queryPairs =
Query
.OrderBy(x => (string)x.Key, StringComparer.OrdinalIgnoreCase)
.Select(x => $"{x.Key}{(x.Value ? "=" : string.Empty)}{x.Value}");
yield return $"?{string.Join("&", queryPairs)}";
}
if (Fragment)
{
yield return $"#{Fragment}";
}
}
#region IEquatable
public bool Equals(SimpleUri other) => Comparer.Equals(this, other);
public bool Equals(string other) => Comparer.Equals(this, other);
public override bool Equals(object obj) => obj is SimpleUri uri && Equals(uri);
public override int GetHashCode() => Comparer.GetHashCode(this);
#endregion
#region operators
public static implicit operator SimpleUri(string uri) => new SimpleUri(uri);
public static implicit operator string(SimpleUri uri) => uri.ToString();
public static SimpleUri operator +(SimpleUri absoluteUri, SimpleUri relativeUri) => new SimpleUri(absoluteUri, relativeUri);
#endregion
}
In this experiment I use a new helper for the first time which is the ImplicitString
. Its purpose is to be able to use a string
as a conditional without having to write any of the string.IsX
all over the place.
public class ImplicitString
{
public ImplicitString(string value) => Value = value;
public string Value { get; }
public override string ToString() => Value;
public static implicit operator ImplicitString(string value) => new ImplicitString(value);
public static implicit operator ImplicitString(Group group) => group.Value;
public static implicit operator string(ImplicitString value) => value.ToString();
public static implicit operator bool(ImplicitString value) => !string.IsNullOrWhiteSpace(value);
}
Example
I tested it with use-cases I currently need it for and it works fine:
new SimpleUri("scheme://authority/p/a/t/h?query#fragment").Dump();
new SimpleUri("scheme:p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h").Dump();
new SimpleUri("file:c:/p/a/t/h").Dump();
What do you say? Is this an optimal implementation or can it be improved?
c# parsing regex dto
I needed some data structure for holding Uris so I thought I try the Uri
class. It quickly turned out that it's very impractical because:
- it's missing an implicit cast from/to string
- it doesn't automatically recognize uris as absolute or relative without specifying the
UriKind
- it doesn't parse the query-string so it cannot compare uris reliably when key-value pairs are in different order
- it's not easy to combine an absolute uri with a relative one
Working with it is just too inconvenient. As a solution I created my own SimpleUri
that should solve these issues. It doesn't support everything yet because I don't need it right now but adding a couple of more regexes later should be a problem.
public class SimpleUri : IEquatable<SimpleUri>, IEquatable<string>
{
// https://regex101.com/r/sd288W/1
// using 'new' for _nicer_ syntax
private static readonly string UriPattern = string.Join(string.Empty, new
{
/* language=regexp */ @"^(?:(?<scheme>w+):)?",
/* language=regexp */ @"(?://(?<authority>w+))?",
/* language=regexp */ @"(?<path>[a-z0-9/:]+)",
/* language=regexp */ @"(?:?(?<query>[a-z0-9=&]+))?",
/* language=regexp */ @"(?:#(?<fragment>[a-z0-9]+))?"
});
public static readonly IEqualityComparer<SimpleUri> Comparer = EqualityComparerFactory<SimpleUri>.Create
(
equals: (x, y) => StringComparer.OrdinalIgnoreCase.Equals(x, y),
getHashCode: (obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj)
);
public SimpleUri([NotNull] string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));
var uriMatch = Regex.Match
(
uri,
UriPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
);
if (!uriMatch.Success)
{
throw new ArgumentException(paramName: nameof(uri), message: $"'{uri}' is not a valid Uri.");
}
Scheme = uriMatch.Groups["scheme"];
Authority = uriMatch.Groups["authority"];
Path = uriMatch.Groups["path"];
Query =
uriMatch.Groups["query"].Success
? Regex
.Matches
(
uriMatch.Groups["query"].Value,
@"(?:^|&)(?<key>[a-z0-9]+)(?:=(?<value>[a-z0-9]+))?",
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
)
.Cast<Match>()
.ToImmutableDictionary
(
m => (ImplicitString)m.Groups["key"],
m => (ImplicitString)m.Groups["value"]
)
: ImmutableDictionary<ImplicitString, ImplicitString>.Empty;
Fragment = uriMatch.Groups["fragment"];
}
public SimpleUri(SimpleUri absoluteUri, SimpleUri relativeUri)
{
if (absoluteUri.IsRelative) throw new ArgumentException($"{nameof(absoluteUri)} must be an absolute Uri.");
if (!relativeUri.IsRelative) throw new ArgumentException($"{nameof(relativeUri)} must be a relative Uri.");
Scheme = absoluteUri.Scheme;
Authority = absoluteUri.Authority;
Path = absoluteUri.Path.Value.TrimEnd('/') + "/" + relativeUri.Path.Value.TrimStart('/');
Query = absoluteUri.Query;
Fragment = absoluteUri.Fragment;
}
public ImplicitString Scheme { get; }
public ImplicitString Authority { get; }
public ImplicitString Path { get; }
public IImmutableDictionary<ImplicitString, ImplicitString> Query { get; }
public ImplicitString Fragment { get; }
public bool IsRelative => !Scheme;
public override string ToString() => string.Join(string.Empty, GetComponents());
private IEnumerable<string> GetComponents()
{
if (Scheme)
{
yield return $"{Scheme}:";
}
if (Authority)
{
yield return $"//{Authority}";
}
yield return Path;
if (Query.Any())
{
var queryPairs =
Query
.OrderBy(x => (string)x.Key, StringComparer.OrdinalIgnoreCase)
.Select(x => $"{x.Key}{(x.Value ? "=" : string.Empty)}{x.Value}");
yield return $"?{string.Join("&", queryPairs)}";
}
if (Fragment)
{
yield return $"#{Fragment}";
}
}
#region IEquatable
public bool Equals(SimpleUri other) => Comparer.Equals(this, other);
public bool Equals(string other) => Comparer.Equals(this, other);
public override bool Equals(object obj) => obj is SimpleUri uri && Equals(uri);
public override int GetHashCode() => Comparer.GetHashCode(this);
#endregion
#region operators
public static implicit operator SimpleUri(string uri) => new SimpleUri(uri);
public static implicit operator string(SimpleUri uri) => uri.ToString();
public static SimpleUri operator +(SimpleUri absoluteUri, SimpleUri relativeUri) => new SimpleUri(absoluteUri, relativeUri);
#endregion
}
In this experiment I use a new helper for the first time which is the ImplicitString
. Its purpose is to be able to use a string
as a conditional without having to write any of the string.IsX
all over the place.
public class ImplicitString
{
public ImplicitString(string value) => Value = value;
public string Value { get; }
public override string ToString() => Value;
public static implicit operator ImplicitString(string value) => new ImplicitString(value);
public static implicit operator ImplicitString(Group group) => group.Value;
public static implicit operator string(ImplicitString value) => value.ToString();
public static implicit operator bool(ImplicitString value) => !string.IsNullOrWhiteSpace(value);
}
Example
I tested it with use-cases I currently need it for and it works fine:
new SimpleUri("scheme://authority/p/a/t/h?query#fragment").Dump();
new SimpleUri("scheme:p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h").Dump();
new SimpleUri("file:c:/p/a/t/h").Dump();
What do you say? Is this an optimal implementation or can it be improved?
c# parsing regex dto
c# parsing regex dto
edited 1 min ago
asked 1 hour ago
t3chb0t
33.8k746111
33.8k746111
TheEqualityComparerFactory
can be found here.
– t3chb0t
1 hour ago
add a comment |
TheEqualityComparerFactory
can be found here.
– t3chb0t
1 hour ago
The
EqualityComparerFactory
can be found here.– t3chb0t
1 hour ago
The
EqualityComparerFactory
can be found here.– t3chb0t
1 hour ago
add a comment |
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209777%2fsimple-uri-parser-and-dto%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209777%2fsimple-uri-parser-and-dto%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
The
EqualityComparerFactory
can be found here.– t3chb0t
1 hour ago