diff --git a/src/Microsoft.Net.Http.Headers/MediaTypeHeaderValue.cs b/src/Microsoft.Net.Http.Headers/MediaTypeHeaderValue.cs
index 4113f44598..173bf7c404 100644
--- a/src/Microsoft.Net.Http.Headers/MediaTypeHeaderValue.cs
+++ b/src/Microsoft.Net.Http.Headers/MediaTypeHeaderValue.cs
@@ -248,6 +248,27 @@ namespace Microsoft.Net.Http.Headers
return true;
}
+ ///
+ /// Performs a deep copy of this object and all of it's NameValueHeaderValue sub components,
+ /// while avoiding the cost of revalidating the components.
+ ///
+ /// A deep copy.
+ public MediaTypeHeaderValue Clone()
+ {
+ var other = new MediaTypeHeaderValue();
+ other._mediaType = _mediaType;
+
+ if (_parameters != null)
+ {
+ other._parameters = new ObjectCollection();
+ foreach (var pair in _parameters)
+ {
+ other._parameters.Add(pair.Clone());
+ }
+ }
+ return other;
+ }
+
public override string ToString()
{
return _mediaType + NameValueHeaderValue.ToString(_parameters, ';', true);
diff --git a/src/Microsoft.Net.Http.Headers/NameValueHeaderValue.cs b/src/Microsoft.Net.Http.Headers/NameValueHeaderValue.cs
index 668a4ccef4..08a08f96ef 100644
--- a/src/Microsoft.Net.Http.Headers/NameValueHeaderValue.cs
+++ b/src/Microsoft.Net.Http.Headers/NameValueHeaderValue.cs
@@ -54,6 +54,19 @@ namespace Microsoft.Net.Http.Headers
}
}
+ ///
+ /// Provides a copy of this object without the cost of re-validating the values.
+ ///
+ /// A copy.
+ public NameValueHeaderValue Clone()
+ {
+ return new NameValueHeaderValue()
+ {
+ _name = _name,
+ _value = _value
+ };
+ }
+
public override int GetHashCode()
{
Contract.Assert(_name != null);
diff --git a/test/Microsoft.Net.Http.Headers.Tests/MediaTypeHeaderValueTest.cs b/test/Microsoft.Net.Http.Headers.Tests/MediaTypeHeaderValueTest.cs
index 5c73d9b607..92ec8f9726 100644
--- a/test/Microsoft.Net.Http.Headers.Tests/MediaTypeHeaderValueTest.cs
+++ b/test/Microsoft.Net.Http.Headers.Tests/MediaTypeHeaderValueTest.cs
@@ -64,6 +64,34 @@ namespace Microsoft.Net.Http.Headers
Assert.Throws(() => mediaType.Parameters.Add(null));
}
+ [Fact]
+ public void Clone_SimpleMediaType_Copied()
+ {
+ var mediaType0 = new MediaTypeHeaderValue("text/plain");
+ var mediaType1 = mediaType0.Clone();
+ Assert.NotSame(mediaType0, mediaType1);
+ Assert.Same(mediaType0.MediaType, mediaType1.MediaType);
+ Assert.NotSame(mediaType0.Parameters, mediaType1.Parameters);
+ Assert.Equal(mediaType0.Parameters.Count, mediaType1.Parameters.Count);
+ }
+
+ [Fact]
+ public void Clone_WithParameters_Copied()
+ {
+ var mediaType0 = new MediaTypeHeaderValue("text/plain");
+ mediaType0.Parameters.Add(new NameValueHeaderValue("name", "value"));
+ var mediaType1 = mediaType0.Clone();
+ Assert.NotSame(mediaType0, mediaType1);
+ Assert.Same(mediaType0.MediaType, mediaType1.MediaType);
+ Assert.NotSame(mediaType0.Parameters, mediaType1.Parameters);
+ Assert.Equal(mediaType0.Parameters.Count, mediaType1.Parameters.Count);
+ var pair0 = mediaType0.Parameters.First();
+ var pair1 = mediaType1.Parameters.First();
+ Assert.NotSame(pair0, pair1);
+ Assert.Same(pair0.Name, pair1.Name);
+ Assert.Same(pair0.Value, pair1.Value);
+ }
+
[Fact]
public void MediaType_SetAndGetMediaType_MatchExpectations()
{
diff --git a/test/Microsoft.Net.Http.Headers.Tests/NameValueHeaderValueTest.cs b/test/Microsoft.Net.Http.Headers.Tests/NameValueHeaderValueTest.cs
index 3d342dea9b..a1e1a935f9 100644
--- a/test/Microsoft.Net.Http.Headers.Tests/NameValueHeaderValueTest.cs
+++ b/test/Microsoft.Net.Http.Headers.Tests/NameValueHeaderValueTest.cs
@@ -59,6 +59,32 @@ namespace Microsoft.Net.Http.Headers
CheckValue("\"quoted string with quoted \\\" quote-pair\"");
}
+ [Fact]
+ public void Clone_NameOnly_SuccesfullyCopied()
+ {
+ var pair0 = new NameValueHeaderValue("name");
+ var pair1 = pair0.Clone();
+ Assert.NotSame(pair0, pair1);
+ Assert.Same(pair0.Name, pair1.Name);
+ Assert.Null(pair0.Value);
+ Assert.Null(pair1.Value);
+ }
+
+ [Fact]
+ public void Clone_NameAndValue_SuccesfullyCopied()
+ {
+ var pair0 = new NameValueHeaderValue("name", "value");
+ var pair1 = pair0.Clone();
+ Assert.NotSame(pair0, pair1);
+ Assert.Same(pair0.Name, pair1.Name);
+ Assert.Same(pair0.Value, pair1.Value);
+
+ // Change one value and verify the other is unchanged.
+ pair1.Value = "othervalue";
+ Assert.Equal("value", pair0.Value);
+ Assert.Equal("othervalue", pair1.Value);
+ }
+
[Fact]
public void Value_CallSetterWithInvalidValues_Throw()
{