Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

memcached transcoder; interner; allow duplicated enums; general bug f…

…ixes

git-svn-id: http://protobuf-net.googlecode.com/svn/trunk@281 b72047a4-3652-0410-9617-b3994939e97b
  • Loading branch information...
commit c2b2804b89c2dfd1e9716891464df44d7263a1d9 1 parent 8721625
marc.gravell authored
View
21 Examples/EnumTests.cs
@@ -2,6 +2,7 @@
using System.IO;
using NUnit.Framework;
using ProtoBuf;
+using System.Runtime.Serialization;
namespace Examples.DesignIdeas
{
@@ -215,6 +216,26 @@ public void TestNegEnumnotDefinedPos()
{
TestNegEnum((NegEnum) 2);
}
+ [Test]
+ public void ShouldBeAbleToSerializeExactDuplicatedEnumValues()
+ {
+ var obj = new HasDuplicatedEnumProp { Value = NastDuplicates.B };
+ var clone = Serializer.DeepClone(obj);
+ Assert.AreEqual(NastDuplicates.A, clone.Value);
+ Assert.AreEqual(NastDuplicates.B, clone.Value);
+ }
+ [ProtoContract]
+ class HasDuplicatedEnumProp
+ {
+ [ProtoMember(1)]
+ public NastDuplicates Value { get; set; }
+ }
+ enum NastDuplicates
+ {
+ None = 0,
+ A = 1,
+ B = 1
+ }
private static void TestNegEnum(NegEnum value)
{
View
9 Examples/Examples.csproj
@@ -87,6 +87,14 @@
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="Enyim.Caching, Version=1.2.0.0, Culture=neutral, PublicKeyToken=cec98615db04012e, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Tools\Enyim.Caching.dll</HintPath>
+ </Reference>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Tools\log4net.dll</HintPath>
+ </Reference>
<Reference Include="nunit.framework, Version=2.4.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Tools\nunit.framework.dll</HintPath>
@@ -148,6 +156,7 @@
<Compile Include="ItemsWithLengthPrefix.cs" />
<Compile Include="ListAsInterfaceTests.cs" />
<Compile Include="ListTests.cs" />
+ <Compile Include="memcached.cs" />
<Compile Include="NonGeneric.cs" />
<Compile Include="NWind\CompatDb.cs" />
<Compile Include="NWind\DataContext.cs" />
View
11 Examples/app.config
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
+ <sectionGroup name="enyim.com">
+ <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" />
+ </sectionGroup>
</configSections>
<connectionStrings>
<add name="DAL.Properties.Settings.NorthwindConnectionString"
@@ -48,4 +51,12 @@
</serviceBehaviors>
</behaviors>
</system.serviceModel>
+ <enyim.com>
+ <memcached transcoder="ProtoBuf.Caching.Enyim.NetTranscoder, protobuf-net.Extensions">
+ <servers>
+ <add address="127.0.0.1" port="11211" />
+ </servers>
+ <socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:10:00" deadTimeout="00:02:00" />
+ </memcached>
+ </enyim.com>
</configuration>
View
4 ProtoGen/Properties/AssemblyInfo.cs
@@ -33,5 +33,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.275")]
-[assembly: AssemblyFileVersion("1.0.0.275")]
+[assembly: AssemblyVersion("1.0.0.280")]
+[assembly: AssemblyFileVersion("1.0.0.280")]
View
13 SilverlightExtended/SilverlightExtended.csproj
@@ -23,6 +23,11 @@
<CreateTestPage>true</CreateTestPage>
<ValidateXaml>true</ValidateXaml>
<ThrowErrorsInValidation>false</ThrowErrorsInValidation>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -110,17 +115,17 @@
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
- <Generator>MSBuild:MarkupCompilePass1</Generator>
+ <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
</ItemGroup>
<ItemGroup>
<Page Include="Page.xaml">
- <Generator>MSBuild:MarkupCompilePass1</Generator>
+ <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="SummaryDetailsView.xaml">
- <Generator>MSBuild:MarkupCompilePass1</Generator>
+ <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
@@ -135,7 +140,7 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
- <Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\v3.0\Microsoft.Silverlight.CSharp.targets" Condition="" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
View
2  buildkit35.build
@@ -48,7 +48,7 @@
<!-- build mono using nant -->
<RemoveDir Directories="protobuf-net-mono\bin; protobuf-net-mono\bin\docs"/>
- <Exec Command="&quot;%ProgramFiles%\Mono-2.4.2.3\share\NAnt\bin\NAnt&quot; -buildfile:protobuf-net-mono\protobuf-net-mono.build -D:build.release=true" />
+ <Exec Command="&quot;%ProgramFiles%\Mono-2.6\share\NAnt\bin\NAnt&quot; -buildfile:protobuf-net-mono\protobuf-net-mono.build -D:build.release=true" />
<!-- build .NET 2.0 using the C# 2.0 compiler -->
<RemoveDir Directories="protobuf-net\obj; protobuf-net\bin"/>
View
4 protobuf-net.Extensions/Properties/AssemblyInfo.cs
@@ -32,8 +32,8 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.275")]
+[assembly: AssemblyVersion("1.0.0.280")]
#if !CF
-[assembly: AssemblyFileVersion("1.0.0.275")]
+[assembly: AssemblyFileVersion("1.0.0.280")]
#endif
[assembly: CLSCompliant(true)]
View
9 protobuf-net.Extensions/protobuf-net.Extensions.csproj
@@ -14,7 +14,7 @@
<FileAlignment>512</FileAlignment>
<StartupObject>
</StartupObject>
- <TargetFrameworkSubset>Client</TargetFrameworkSubset>
+ <TargetFrameworkSubset>Full</TargetFrameworkSubset>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -40,6 +40,11 @@
<DocumentationFile>bin\Release\protobuf-net.Extensions.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="Enyim.Caching, Version=1.2.0.0, Culture=neutral, PublicKeyToken=cec98615db04012e, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Tools\Enyim.Caching.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core">
@@ -52,6 +57,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Caching\ByteSegmentComparer.cs" />
+ <Compile Include="Caching\Enyim\ProtoTranscoder.cs" />
<Compile Include="Expressions\Expression.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceModel\Client\ProtoClientExtensions.cs" />
View
17 protobuf-net/AttributeUtils.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Reflection;
namespace ProtoBuf
@@ -9,6 +9,14 @@ internal static class AttributeUtils
{
return (T)Attribute.GetCustomAttribute(member, typeof(T));
}
+ internal static Attribute GetAttribute(MemberInfo member, string fullName) {
+ foreach(Attribute attrib in Attribute.GetCustomAttributes(member)) {
+ if(attrib.GetType().FullName == fullName) {
+ return attrib;
+ }
+ }
+ return null;
+ }
internal static T GetAttribute<T>(Type type) where T : Attribute
{
@@ -23,5 +31,12 @@ internal static class AttributeUtils
}
return null;
}
+
+ public static T GetValue<T>(Attribute attribute, string propertyName)
+ {
+ PropertyInfo prop = attribute.GetType().GetProperty(propertyName);
+ if(prop == null) throw new ArgumentException("Missing property: " + propertyName);
+ return (T)prop.GetValue(attribute, null);
+ }
}
}
View
13 protobuf-net/Entity.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
@@ -56,20 +56,15 @@ public static bool IsEntity(Type type)
break;
}
}
-#if NET_3_0
if(!isEntity) {
- for (int i = 0; i < attribs.Length; i++)
- {
- if (attribs[i] is DataContractAttribute)
- {
- DataContractAttribute dca = (DataContractAttribute)attribs[i];
- name = dca.Name;
+ for (int i = 0; i < attribs.Length; i++) {
+ if (attribs[i].GetType().FullName == Serializer.DataContractAttributeFullName) {
+ Serializer.ParseDataContractAttribute(attribs[i], out name);
isEntity = true;
break;
}
}
}
-#endif
if(!isEntity) {
for (int i = 0; i < attribs.Length; i++)
{
View
6 protobuf-net/GlobalOptions.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Text;
using ProtoBuf.Property;
@@ -12,8 +12,6 @@ public static partial class Serializer
/// </summary>
public static class GlobalOptions
{
- #if NET_3_0
-
private static bool inferTagFromName;
/// <summary>
/// Global default for that
@@ -28,8 +26,6 @@ public static bool InferTagFromName
get { return inferTagFromName; }
set { inferTagFromName = value; }
}
-
- #endif
}
internal static bool HasAddMethod(Type list, Type item)
View
39 protobuf-net/NonGeneric.cs
@@ -27,21 +27,44 @@ public static void SerializeWithLengthPrefix(Stream destination, object instance
BindingFlags.Static | BindingFlags.Public))
{
ParameterInfo[] p;
- if (method.Name == "SerializeWithLengthPrefix" && method.IsGenericMethod
- && (p = method.GetParameters()).Length == 4
- && p[0].ParameterType == typeof(Stream)
- && p[2].ParameterType == typeof(PrefixStyle)
- && p[3].ParameterType == typeof(int))
+ if (method.Name == "SerializeWithLengthPrefix" && method.IsGenericMethod)
{
- method.MakeGenericMethod(instance.GetType()).Invoke(
- null, new object[] { destination, instance, style, tag });
- return;
+ MethodInfo genericMethod = method.MakeGenericMethod(instance.GetType());
+ if((p = genericMethod.GetParameters()).Length == 4
+ && p[0].ParameterType == typeof(Stream)
+ && p[2].ParameterType == typeof(PrefixStyle)
+ && p[3].ParameterType == typeof(int))
+ {
+ genericMethod.Invoke(
+ null, new object[] { destination, instance, style, tag });
+ return;
+ }
}
}
throw new ProtoException("Unable to resolve SerializeWithLengthPrefix method");
}
/// <summary>
+ /// Can the given type be meaningfully with protobuf-net?
+ /// </summary>
+ public static bool CanSerialize(Type type)
+ {
+ if (type == null) throw new ArgumentNullException("type");
+ if (type.IsValueType) return false;
+
+ // serialize as item?
+ if (Serializer.IsEntityType(type)) return true;
+
+ // serialize as list?
+ bool enumOnly;
+ Type itemType = PropertyFactory.GetListType(type, out enumOnly);
+ if (itemType != null
+ && (!enumOnly || Serializer.HasAddMethod(type, itemType))
+ && Serializer.IsEntityType(itemType)) return true;
+ return false;
+ }
+
+ /// <summary>
/// Writes a protocol-buffer representation of the given instance to the supplied stream.
/// </summary>
/// <param name="instance">The existing instance to be serialized (cannot be null).</param>
View
2  protobuf-net/PrefixStyle.cs
@@ -15,7 +15,7 @@ public enum PrefixStyle
/// </summary>
Base128,
/// <summary>
- /// A fixed-length (big-endian) length prefix is applied to the data (useful for compatibility).
+ /// A fixed-length (little-endian) length prefix is applied to the data (useful for compatibility).
/// </summary>
Fixed32
}
View
4 protobuf-net/Properties/AssemblyInfo.cs
@@ -33,8 +33,8 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.275")]
+[assembly: AssemblyVersion("1.0.0.280")]
#if !CF
-[assembly: AssemblyFileVersion("1.0.0.275")]
+[assembly: AssemblyFileVersion("1.0.0.280")]
#endif
[assembly: CLSCompliant(true)]
View
19 protobuf-net/Property/PropertyEnum.cs
@@ -22,17 +22,26 @@ internal sealed class PropertyEnum<TSource,TEnum> : Property<TSource, TEnum>
List<KeyValuePair<TEnum, int>> list = new List<KeyValuePair<TEnum, int>>();
foreach (Serializer.ProtoEnumValue<TEnum> value in Serializer.GetEnumValues<TEnum>())
{
+ bool add = true;
foreach (KeyValuePair<TEnum, int> existing in list)
{
- if ((existing.Value == value.WireValue) || enumComparer.Equals(existing.Key, value.EnumValue))
+ int match = 0;
+ if (existing.Value == value.WireValue) match++;
+ if (enumComparer.Equals(existing.Key, value.EnumValue)) match++;
+ switch(match)
{
- errMsg = string.Format("The enum {0} has conflicting values {1} and {2}",
+ case 2:
+ add = false;
+ break; // exact dup in the enum definition; it doesn't matter
+ case 1:
+ errMsg = string.Format("The enum {0} has conflicting values {1} and {2}",
typeof(TEnum), existing.Key, value.Name);
- return; // but throw from the *regular* ctor to prevent obscure type init errors
+ return; // but throw from the *regular* ctor to prevent obscure type init errors
}
}
-
- list.Add(new KeyValuePair<TEnum, int>(value.EnumValue, value.WireValue));
+ if (add) {
+ list.Add(new KeyValuePair<TEnum, int>(value.EnumValue, value.WireValue));
+ }
}
values = list.ToArray();
View
2  protobuf-net/Property/PropertyString.cs
@@ -70,7 +70,7 @@ public override string DeserializeImpl(TSource source, SerializationContext cont
{
if (len > SerializationContext.InitialBufferLength) context.CheckSpace(len);
context.ReadBlock(len);
- value = utf8.GetString(context.Workspace, 0, len);
+ value = context.Intern(utf8.GetString(context.Workspace, 0, len));
}
return value;
View
5 protobuf-net/ProtoContractAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace ProtoBuf
{
@@ -37,7 +37,7 @@ public int ImplicitFirstTag
public ImplicitFields ImplicitFields { get { return implicitFields; } set { implicitFields = value; } }
private ImplicitFields implicitFields;
- #if NET_3_0
+
private bool? inferTagFromName;
/// <summary>
@@ -70,6 +70,5 @@ public int DataMemberOffset
set { dataMemberOffset = value; }
}
- #endif
}
}
View
16 protobuf-net/SerializationContext.cs
@@ -4,6 +4,7 @@
using System.IO;
#if !SILVERLIGHT && !CF
using System.Runtime.Serialization;
+using System.Collections;
#endif
namespace ProtoBuf
@@ -262,13 +263,24 @@ public void ReadFrom(SerializationContext context)
this.ioBufferIndex = context.ioBufferIndex;
this.inputStreamAvailable = context.inputStreamAvailable;
this.ioBufferEffectiveSize = context.ioBufferEffectiveSize;
-
+ this.stringCache = context.stringCache;
TraceChangeOrigin(context); // note ConditionalAttribute
// IMPORTANT: don't copy the group stack; we want to
// validate that the group-stack is empty when finding the end of a stream
}
-
+ private Dictionary<string, string> stringCache;
+ public string Intern(string value)
+ {
+ if (stringCache == null) stringCache = new Dictionary<string, string>(StringComparer.Ordinal);
+ string result;
+ if (!stringCache.TryGetValue(value, out result))
+ {
+ stringCache.Add(value, value);
+ result = value;
+ }
+ return result;
+ }
public static void Reverse4(byte[] buffer, int index)
{
byte tmp = buffer[index + 0];
View
57 protobuf-net/Serializer.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
@@ -75,7 +75,8 @@ static void AddImplicitByDeclaringType<T>(Type declaringType, List<MemberInfo> l
&& TryGetTag(member, out tag, out name, true, out fmt, out options) && tag < 1) list.Add(member);
}
}
-
+ internal const string DataMemberAttributeFullName = "System.Runtime.Serialization.DataMemberAttribute";
+ internal const string DataContractAttributeFullName = "System.Runtime.Serialization.DataContractAttribute";
internal static bool TryGetTag(MemberInfo member, out int tag, out string name, bool callerIsTagInference, out DataFormat format, out MemberSerializationOptions options)
{
name = member.Name;
@@ -157,13 +158,21 @@ internal static bool TryGetTag(MemberInfo member, out int tag, out string name,
}
return false;
}
-
+
#if NET_3_0
- DataMemberAttribute dm = AttributeUtils.GetAttribute<DataMemberAttribute>(member);
+ DataMemberAttribute dm = AttributeUtils.GetAttribute<DataMemberAttribute>(member);
+#else
+ Attribute dm = AttributeUtils.GetAttribute(member, DataMemberAttributeFullName);
+#endif
if (dm != null)
{
- if (!string.IsNullOrEmpty(dm.Name)) name = dm.Name;
- tag = dm.Order;
+ string dmName;
+ int dmOrder;
+ bool dmIsRequired;
+ ParseDataMemberAttribute(dm, out dmName, out dmOrder, out dmIsRequired);
+
+ if (!string.IsNullOrEmpty(dmName)) name = dmName;
+ tag = dmOrder;
if (pca != null) tag += pca.DataMemberOffset;
if(!callerIsTagInference) // avoid infinite recursion
@@ -213,10 +222,9 @@ internal static bool TryGetTag(MemberInfo member, out int tag, out string name,
}
}
}
- if(dm.IsRequired) options |= MemberSerializationOptions.Required;
+ if(dmIsRequired) options |= MemberSerializationOptions.Required;
return callerIsTagInference || tag > 0;
}
-#endif
XmlElementAttribute xe = AttributeUtils.GetAttribute<XmlElementAttribute>(member);
if (xe != null)
@@ -237,6 +245,39 @@ internal static bool TryGetTag(MemberInfo member, out int tag, out string name,
return false;
}
+ internal static void ParseDataContractAttribute(
+ Attribute attribute, out string name)
+ {
+ if (attribute == null) throw new ArgumentNullException("attribute");
+#if NET_3_0
+ name = ((DataContractAttribute)attribute).Name;
+#else
+ name = AttributeUtils.GetValue<string>(attribute, "Name");
+#endif
+ }
+
+
+ internal static void ParseDataMemberAttribute (
+#if NET_3_0
+ DataMemberAttribute attribute,
+#else
+ Attribute attribute,
+#endif
+ out string name, out int order, out bool isRequired)
+ {
+ if(attribute == null) throw new ArgumentNullException("attribute");
+#if NET_3_0
+ name = attribute.Name;
+ order = attribute.Order;
+ isRequired = attribute.IsRequired;
+#else
+ name = AttributeUtils.GetValue<string>(attribute, "Name");
+ order = AttributeUtils.GetValue<int>(attribute, "Order");
+ isRequired = AttributeUtils.GetValue<bool>(attribute,"IsRequired");
+#endif
+ }
+
+
/// <summary>
/// Creates a new instance from a protocol-buffer stream
/// </summary>
View
17 protobuf-net/ServiceModel/ProtoOperationBehavior.cs
@@ -12,26 +12,11 @@ internal sealed class ProtoOperationBehavior : DataContractSerializerOperationBe
public ProtoOperationBehavior(OperationDescription operation) : base(operation) { }
//public ProtoOperationBehavior(OperationDescription operation, DataContractFormatAttribute dataContractFormat) : base(operation, dataContractFormat) { }
- internal static bool CanSerialize(Type type)
- {
- if (type == null) throw new ArgumentNullException("type");
- if (type.IsValueType) return false;
-
- // serialize as item?
- if (Serializer.IsEntityType(type)) return true;
- // serialize as list?
- bool enumOnly;
- Type itemType = PropertyFactory.GetListType(type, out enumOnly);
- if (itemType != null
- && (!enumOnly || Serializer.HasAddMethod(type, itemType))
- && Serializer.IsEntityType(itemType)) return true;
- return false;
- }
public override XmlObjectSerializer CreateSerializer(Type type, System.Xml.XmlDictionaryString name, System.Xml.XmlDictionaryString ns, IList<Type> knownTypes)
{
- if (CanSerialize(type))
+ if (Serializer.NonGeneric.CanSerialize(type))
{
return (XmlObjectSerializer)typeof(XmlProtoSerializer<>)
.MakeGenericType(type)
Please sign in to comment.
Something went wrong with that request. Please try again.