[prev in list] [next in list] [prev in thread] [next in thread] 

List:       avro-commits
Subject:    svn commit: r1540206 [1/2] - in /avro/trunk/lang/csharp/src/apache: main/Generic/ main/Specific/ per
From:       cutting () apache ! org
Date:       2013-11-08 22:15:03
Message-ID: 20131108221503.C0C8B23888E7 () eris ! apache ! org
[Download RAW message or body]

Author: cutting
Date: Fri Nov  8 22:15:02 2013
New Revision: 1540206

URL: http://svn.apache.org/r1540206
Log:
AVRO-1332.  Add missing files and fix a bug with defaults.  Contributed by David \
McIntosh.

Added:
    avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs
    avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs
    avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs
    avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs
    avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs
    avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs
    avro/trunk/lang/csharp/src/apache/perf/
    avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj
    avro/trunk/lang/csharp/src/apache/perf/PerfTest.cs
    avro/trunk/lang/csharp/src/apache/perf/com/
    avro/trunk/lang/csharp/src/apache/perf/com/foo/
    avro/trunk/lang/csharp/src/apache/perf/com/foo/A.cs
    avro/trunk/lang/csharp/src/apache/perf/com/foo/Complex.cs
    avro/trunk/lang/csharp/src/apache/perf/com/foo/MyEnum.cs
    avro/trunk/lang/csharp/src/apache/perf/com/foo/MyFixed.cs
    avro/trunk/lang/csharp/src/apache/perf/com/foo/Narrow.cs
    avro/trunk/lang/csharp/src/apache/perf/com/foo/Simple.cs
    avro/trunk/lang/csharp/src/apache/perf/com/foo/Wide.cs
    avro/trunk/lang/csharp/src/apache/perf/com/foo/newRec.cs
    avro/trunk/lang/csharp/src/apache/perf/schema.avsc
Modified:
    avro/trunk/lang/csharp/src/apache/test/Generic/GenericTests.cs

Added: avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs?rev=1540206&view=auto
 ==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs Fri Nov  8 \
22:15:02 2013 @@ -0,0 +1,211 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using Avro.IO;
+
+namespace Avro.Generic
+{
+    /// PreresolvingDatumReader for reading data to GenericRecord classes or \
primitives. +    /// <see cref="PreresolvingDatumReader{T}">For more information \
about performance considerations for choosing this implementation</see> +    public \
class GenericDatumReader<T> : PreresolvingDatumReader<T> +    {
+        public GenericDatumReader(Schema writerSchema, Schema readerSchema) : \
base(writerSchema, readerSchema) +        {
+        }
+
+        protected override bool IsReusable(Schema.Type tag)
+        {
+            switch (tag)
+            {
+                case Schema.Type.Double:
+                case Schema.Type.Boolean:
+                case Schema.Type.Int:
+                case Schema.Type.Long:
+                case Schema.Type.Float:
+                case Schema.Type.Bytes:
+                case Schema.Type.String:
+                case Schema.Type.Null:
+                    return false;
+            }
+            return true;
+        }
+
+        protected override ArrayAccess GetArrayAccess(ArraySchema readerSchema)
+        {
+            return new GenericArrayAccess();
+        }
+
+        protected override EnumAccess GetEnumAccess(EnumSchema readerSchema)
+        {
+            return new GenericEnumAccess(readerSchema);
+        }
+
+        protected override MapAccess GetMapAccess(MapSchema readerSchema)
+        {
+            return new GenericMapAccess();
+        }
+
+        protected override RecordAccess GetRecordAccess(RecordSchema readerSchema)
+        {
+            return new GenericRecordAccess(readerSchema);
+        }
+
+        protected override FixedAccess GetFixedAccess(FixedSchema readerSchema)
+        {
+            return new GenericFixedAccess(readerSchema);
+        }
+
+        class GenericEnumAccess : EnumAccess
+        {
+            private EnumSchema schema;
+
+            public GenericEnumAccess(EnumSchema schema)
+            {
+                this.schema = schema;
+            }
+
+            public object CreateEnum(object reuse, int ordinal)
+            {
+                if (reuse is GenericEnum)
+                {
+                    var ge = (GenericEnum) reuse;
+                    if (ge.Schema.Equals(this.schema))
+                    {
+                        ge.Value = this.schema[ordinal];
+                        return ge;
+                    }
+                }
+                return new GenericEnum(this.schema, this.schema[ordinal]);
+            }
+        }
+
+        internal class GenericRecordAccess : RecordAccess
+        {
+            private RecordSchema schema;
+
+            public GenericRecordAccess(RecordSchema schema)
+            {
+                this.schema = schema;
+            }
+
+            public object CreateRecord(object reuse)
+            {
+                GenericRecord ru = (reuse == null || !(reuse is GenericRecord) || \
!(reuse as GenericRecord).Schema.Equals(this.schema)) ? +                    new \
GenericRecord(this.schema) : +                    reuse as GenericRecord;
+                return ru;
+            }
+
+            public object GetField(object record, string fieldName, int fieldPos)
+            {
+                object result;
+                if(!((GenericRecord)record).TryGetValue(fieldName, out result))
+                {
+                    return null;
+                }
+                return result;
+            }
+
+            public void AddField(object record, string fieldName, int fieldPos, \
object fieldValue) +            {
+                ((GenericRecord)record).Add(fieldName, fieldValue);
+            }
+        }
+
+        class GenericFixedAccess : FixedAccess
+        {
+            private FixedSchema schema;
+
+            public GenericFixedAccess(FixedSchema schema)
+            {
+                this.schema = schema;
+            }
+
+            public object CreateFixed(object reuse)
+            {
+                return (reuse is GenericFixed && (reuse as \
GenericFixed).Schema.Equals(this.schema)) ? +                    reuse : new \
GenericFixed(this.schema); +            }
+
+            public byte[] GetFixedBuffer( object f )
+            {
+                return ((GenericFixed)f).Value;
+            }
+        }
+
+        class GenericArrayAccess : ArrayAccess
+        {
+            public object Create(object reuse)
+            {
+                    return (reuse is object[]) ? reuse : new object[0];
+            }
+
+            public void EnsureSize(ref object array, int targetSize)
+            {
+                if (((object[])array).Length < targetSize)
+                    SizeTo(ref array, targetSize);
+            }
+
+            public void Resize(ref object array, int targetSize)
+            {
+                SizeTo(ref array, targetSize);
+            }
+
+            public void AddElements( object arrayObj, int elements, int index, \
ReadItem itemReader, Decoder decoder, bool reuse ) +            {
+                var array = (object[]) arrayObj;
+                for (int i = index; i < index + elements; i++)
+                {
+                    array[i] = reuse ? itemReader(array[i], decoder) : \
itemReader(null, decoder); +                }
+            }
+
+            private static void SizeTo(ref object array, int targetSize)
+            {
+                var o = (object[]) array;
+                Array.Resize(ref o, targetSize);
+                array = o;
+            }
+        }
+
+        class GenericMapAccess : MapAccess
+        {
+            public object Create(object reuse)
+            {
+                if (reuse is IDictionary<string, object>)
+                {
+                    var result = (IDictionary<string, object>)reuse;
+                    result.Clear();
+                    return result;
+                }
+                return new Dictionary<string, object>();
+            }
+
+            public void AddElements(object mapObj, int elements, ReadItem \
itemReader, Decoder decoder, bool reuse) +            {
+                var map = ((IDictionary<string, object>)mapObj);
+                for (int i = 0; i < elements; i++)
+                {
+                    var key = decoder.ReadString();
+                    map[key] = itemReader(null, decoder);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

Added: avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs?rev=1540206&view=auto
 ==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs Fri Nov  8 \
22:15:02 2013 @@ -0,0 +1,147 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using Encoder = Avro.IO.Encoder;
+
+namespace Avro.Generic
+{
+    /// <summary>
+    /// PreresolvingDatumWriter for writing data from GenericRecords or primitive \
types. +    /// <see cref="PreresolvingDatumWriter{T}">For more information about \
performance considerations for choosing this implementation</see> +    /// </summary>
+    public class GenericDatumWriter<T> : PreresolvingDatumWriter<T>
+    {
+        public GenericDatumWriter( Schema schema ) : base(schema, new \
GenericArrayAccess(), new DictionaryMapAccess()) +        {
+        }
+
+        protected override void WriteRecordFields(object recordObj, \
RecordFieldWriter[] writers, Encoder encoder) +        {
+            var record = (GenericRecord) recordObj;
+            foreach (var writer in writers)
+            {
+                writer.WriteField(record[writer.Field.Name], encoder);
+            }
+        }
+
+        protected override void EnsureRecordObject( RecordSchema recordSchema, \
object value ) +        {
+            if( value == null || !( value is GenericRecord ) || !( ( value as \
GenericRecord ).Schema.Equals( recordSchema ) ) ) +            {
+                throw TypeMismatch( value, "record", "GenericRecord" );
+            }
+        }
+
+        protected override void WriteField(object record, string fieldName, int \
fieldPos, WriteItem writer, Encoder encoder) +        {
+            writer(((GenericRecord)record)[fieldName], encoder);
+        }
+
+        protected override WriteItem ResolveEnum(EnumSchema es)
+        {
+            return (v,e) =>
+                       {
+                            if( v == null || !(v is GenericEnum) || !((v as \
GenericEnum).Schema.Equals(es))) +                                throw \
TypeMismatch(v, "enum", "GenericEnum"); +                            \
e.WriteEnum(es.Ordinal((v as GenericEnum ).Value)); +                       };
+        }
+
+        protected override void WriteFixed( FixedSchema es, object value, Encoder \
encoder ) +        {
+            if (value == null || !(value is GenericFixed) || !(value as \
GenericFixed).Schema.Equals(es)) +            {
+                throw TypeMismatch(value, "fixed", "GenericFixed");
+            }
+            GenericFixed ba = (GenericFixed)value;
+            encoder.WriteFixed(ba.Value);
+        }
+
+        /*
+         * FIXME: This method of determining the Union branch has problems. If the \
data is IDictionary<string, object> +         * if there are two branches one with \
record schema and the other with map, it choose the first one. Similarly if +         \
* the data is byte[] and there are fixed and bytes schemas as branches, it choose the \
first one that matches. +         * Also it does not recognize the arrays of \
primitive types. +         */
+        protected override bool UnionBranchMatches(Schema sc, object obj)
+        {
+            if (obj == null && sc.Tag != Avro.Schema.Type.Null) return false;
+            switch (sc.Tag)
+            {
+                case Schema.Type.Null:
+                    return obj == null;
+                case Schema.Type.Boolean:
+                    return obj is bool;
+                case Schema.Type.Int:
+                    return obj is int;
+                case Schema.Type.Long:
+                    return obj is long;
+                case Schema.Type.Float:
+                    return obj is float;
+                case Schema.Type.Double:
+                    return obj is double;
+                case Schema.Type.Bytes:
+                    return obj is byte[];
+                case Schema.Type.String:
+                    return obj is string;
+                case Schema.Type.Error:
+                case Schema.Type.Record:
+                    //return obj is GenericRecord && (obj as \
GenericRecord).Schema.Equals(s); +                    return obj is GenericRecord && \
(obj as GenericRecord).Schema.SchemaName.Equals((sc as RecordSchema).SchemaName); +   \
case Schema.Type.Enumeration: +                    //return obj is GenericEnum && \
(obj as GenericEnum).Schema.Equals(s); +                    return obj is GenericEnum \
&& (obj as GenericEnum).Schema.SchemaName.Equals((sc as EnumSchema).SchemaName); +    \
case Schema.Type.Array: +                    return obj is Array && !(obj is byte[]);
+                case Schema.Type.Map:
+                    return obj is IDictionary<string, object>;
+                case Schema.Type.Union:
+                    return false;   // Union directly within another union not \
allowed! +                case Schema.Type.Fixed:
+                    //return obj is GenericFixed && (obj as \
GenericFixed).Schema.Equals(s); +                    return obj is GenericFixed && \
(obj as GenericFixed).Schema.SchemaName.Equals((sc as FixedSchema).SchemaName); +     \
default: +                    throw new AvroException("Unknown schema type: " + \
sc.Tag); +            }
+        }
+
+        private class GenericArrayAccess : ArrayAccess
+        {
+            public void EnsureArrayObject( object value )
+            {
+                if( value == null || !( value is Array ) ) throw TypeMismatch( \
value, "array", "Array" ); +            }
+
+            public long GetArrayLength( object value )
+            {
+                return ( (Array) value ).Length;
+            }
+
+            public void WriteArrayValues(object array, WriteItem valueWriter, \
Encoder encoder) +            {
+                var arrayInstance = (Array) array;
+                for(int i = 0; i < arrayInstance.Length; i++)
+                {
+                    encoder.StartItem();
+                    valueWriter(arrayInstance.GetValue(i), encoder);
+                }
+            }
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs?rev=1540206&view=auto
 ==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs Fri Nov \
8 22:15:02 2013 @@ -0,0 +1,596 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections.Generic;
+using System.IO;
+using Avro.IO;
+
+namespace Avro.Generic
+{
+    /// <summary>
+    /// A general purpose reader of data from avro streams. This reader analyzes and \
resolves the reader and writer schemas +    /// when constructed so that reads can be \
more efficient. Once constructed, a reader can be reused or shared among threads +    \
/// to avoid incurring more resolution costs. +    /// </summary>
+    public abstract class PreresolvingDatumReader<T> : DatumReader<T>
+    {
+        public Schema ReaderSchema { get; private set; }
+        public Schema WriterSchema { get; private set; }
+
+        protected delegate object ReadItem(object reuse, Decoder dec);
+        
+        // read a specific field from a decoder
+        private delegate object DecoderRead(Decoder dec);
+        // skip specific field(s) from a decoder
+        private delegate void DecoderSkip(Decoder dec);
+        // read & set fields on a record
+        private delegate void FieldReader(object record, Decoder decoder);
+
+        private readonly ReadItem _reader;
+        private readonly Dictionary<SchemaPair,ReadItem> _recordReaders = new \
Dictionary<SchemaPair,ReadItem>(); +        
+        protected PreresolvingDatumReader(Schema writerSchema, Schema readerSchema)
+        {
+            ReaderSchema = readerSchema;
+            WriterSchema = writerSchema;
+            if (!ReaderSchema.CanRead(WriterSchema))
+                throw new AvroException("Schema mismatch. Reader: " + ReaderSchema + \
", writer: " + WriterSchema); +            _reader = ResolveReader(writerSchema, \
readerSchema); +        }
+
+        public T Read(T reuse, Decoder decoder)
+        {
+            return (T)_reader(reuse, decoder);
+        }
+
+        protected abstract ArrayAccess GetArrayAccess(ArraySchema readerSchema);
+        protected abstract EnumAccess GetEnumAccess(EnumSchema readerSchema);
+        protected abstract MapAccess GetMapAccess(MapSchema readerSchema);
+        protected abstract RecordAccess GetRecordAccess(RecordSchema readerSchema);
+        protected abstract FixedAccess GetFixedAccess(FixedSchema readerSchema);
+
+        /// <summary>
+        /// Build a reader that accounts for schema differences between the reader \
and writer schemas. +        /// </summary>
+        private ReadItem ResolveReader(Schema writerSchema, Schema readerSchema)
+        {
+            if (readerSchema.Tag == Schema.Type.Union && writerSchema.Tag != \
Schema.Type.Union) +            {
+                readerSchema = FindBranch(readerSchema as UnionSchema, \
writerSchema); +            }
+            switch (writerSchema.Tag)
+            {
+                case Schema.Type.Null:
+                    return ReadNull;
+                case Schema.Type.Boolean:
+                    return ReadBoolean;
+                case Schema.Type.Int:
+                    {
+                        switch (readerSchema.Tag)
+                        {
+                            case Schema.Type.Long:
+                                return Read(d => (long) d.ReadInt());
+                            case Schema.Type.Float:
+                                return Read(d => (float) d.ReadInt());
+                            case Schema.Type.Double:
+                                return Read(d => (double) d.ReadInt());
+                            default:
+                                return Read(d => d.ReadInt());
+                        }
+                    }
+                case Schema.Type.Long:
+                    {
+                        switch (readerSchema.Tag)
+                        {
+                            case Schema.Type.Float:
+                                return Read(d => (float) d.ReadLong());
+                            case Schema.Type.Double:
+                                return Read(d => (double) d.ReadLong());
+                            default:
+                                return Read(d => d.ReadLong());
+                        }
+                    }
+                case Schema.Type.Float:
+                    {
+                        switch (readerSchema.Tag)
+                        {
+                            case Schema.Type.Double:
+                                return Read(d => (double) d.ReadFloat());
+                            default:
+                                return Read(d => d.ReadFloat());
+                        }
+                    }
+                case Schema.Type.Double:
+                    return Read(d => d.ReadDouble());
+                case Schema.Type.String:
+                    return Read(d => d.ReadString());
+                case Schema.Type.Bytes:
+                    return Read(d => d.ReadBytes());
+                case Schema.Type.Error:
+                case Schema.Type.Record:
+                    return ResolveRecord((RecordSchema)writerSchema, \
(RecordSchema)readerSchema); +                case Schema.Type.Enumeration:
+                    return ResolveEnum((EnumSchema)writerSchema, \
(EnumSchema)readerSchema); +                case Schema.Type.Fixed:
+                    return ResolveFixed((FixedSchema)writerSchema, \
(FixedSchema)readerSchema); +                case Schema.Type.Array:
+                    return ResolveArray((ArraySchema)writerSchema, \
(ArraySchema)readerSchema); +                case Schema.Type.Map:
+                    return ResolveMap((MapSchema)writerSchema, \
(MapSchema)readerSchema); +                case Schema.Type.Union:
+                    return ResolveUnion((UnionSchema)writerSchema, readerSchema);
+                default:
+                    throw new AvroException("Unknown schema type: " + writerSchema);
+            }
+        }
+
+        private ReadItem ResolveEnum(EnumSchema writerSchema, EnumSchema \
readerSchema) +        {
+            var enumAccess = GetEnumAccess(readerSchema);
+
+            if (readerSchema.Equals(writerSchema))
+            {
+                return (r, d) => enumAccess.CreateEnum(r, d.ReadEnum());
+            }
+
+            var translator = new int[writerSchema.Symbols.Count];
+
+            foreach (var symbol in writerSchema.Symbols)
+            {
+                var writerOrdinal = writerSchema.Ordinal(symbol);
+                if (readerSchema.Contains(symbol))
+                {
+                    translator[writerOrdinal] = readerSchema.Ordinal(symbol);
+                }
+                else
+                {
+                    translator[writerOrdinal] = -1;
+                }
+            }
+
+            return (r, d) =>
+                        {
+                            var writerOrdinal = d.ReadEnum();
+                            var readerOrdinal = translator[writerOrdinal];
+                            if (readerOrdinal == -1)
+                            {
+                                throw new AvroException("No such symbol: " + \
writerSchema[writerOrdinal]); +                            }
+                            return enumAccess.CreateEnum(r, readerOrdinal);
+                        };
+        }
+
+        private ReadItem ResolveRecord(RecordSchema writerSchema, RecordSchema \
readerSchema) +        {
+            var schemaPair = new SchemaPair(writerSchema, readerSchema);
+            ReadItem recordReader;
+
+            if (_recordReaders.TryGetValue(schemaPair, out recordReader))
+            {
+                return recordReader;
+            }
+
+            FieldReader[] fieldReaderArray = null;
+            var recordAccess = GetRecordAccess(readerSchema);
+
+            recordReader = (r, d) => ReadRecord(r, d, recordAccess, \
fieldReaderArray); +            _recordReaders.Add(schemaPair, recordReader);
+
+            var readSteps = new List<FieldReader>();
+
+            foreach (Field wf in writerSchema)
+            {
+                Field rf;
+                if (readerSchema.TryGetFieldAlias(wf.Name, out rf))
+                {
+                    var readItem = ResolveReader(wf.Schema, rf.Schema);
+                    if(IsReusable(rf.Schema.Tag))
+                    {
+                        readSteps.Add((rec,d) => recordAccess.AddField(rec, rf.Name, \
rf.Pos, +                            readItem(recordAccess.GetField(rec, rf.Name, \
rf.Pos), d))); +                    }
+                    else
+                    {
+                        readSteps.Add((rec, d) => recordAccess.AddField(rec, \
rf.Name, rf.Pos, +                            readItem(null, d)));
+                    }
+                }
+                else
+                {
+                    var skip = GetSkip(wf.Schema);
+                    readSteps.Add((rec, d) => skip(d));
+                }
+            }
+
+            // fill in defaults for any reader fields not in the writer schema
+            foreach (Field rf in readerSchema)
+            {
+                if (writerSchema.Contains(rf.Name)) continue;
+
+                var defaultStream = new MemoryStream();
+                var defaultEncoder = new BinaryEncoder(defaultStream);
+
+                defaultStream.Position = 0; // reset for writing
+                Resolver.EncodeDefaultValue(defaultEncoder, rf.Schema, \
rf.DefaultValue); +                defaultStream.Flush();
+	            var defaultBytes = defaultStream.ToArray();
+
+                var readItem = ResolveReader(rf.Schema, rf.Schema);
+
+                var rfInstance = rf;
+                if(IsReusable(rf.Schema.Tag))
+                {
+                    readSteps.Add((rec, d) => recordAccess.AddField(rec, \
rfInstance.Name, rfInstance.Pos, +                        \
readItem(recordAccess.GetField(rec, rfInstance.Name, rfInstance.Pos), +               \
new BinaryDecoder(new MemoryStream( defaultBytes))))); +                }
+                else
+                {
+                    readSteps.Add((rec, d) => recordAccess.AddField(rec, \
rfInstance.Name, rfInstance.Pos, +                        readItem(null, new \
BinaryDecoder(new MemoryStream(defaultBytes))))); +                }
+            }
+
+            fieldReaderArray = readSteps.ToArray();
+            return recordReader;
+        }
+
+        private object ReadRecord(object reuse, Decoder decoder, RecordAccess \
recordAccess, IEnumerable<FieldReader> readSteps ) +        {
+            var rec = recordAccess.CreateRecord(reuse);
+            foreach (FieldReader fr in readSteps)
+            {
+                fr(rec, decoder);
+                // TODO: on exception, report offending field
+            }
+            return rec;
+        }
+
+        private ReadItem ResolveUnion(UnionSchema writerSchema, Schema readerSchema)
+        {
+            var lookup = new ReadItem[writerSchema.Count];
+
+            for (int i = 0; i < writerSchema.Count; i++)
+            {
+                var writerBranch = writerSchema[i];
+
+                if (readerSchema is UnionSchema)
+                {
+                    var unionReader = (UnionSchema) readerSchema;
+                    var readerBranch = unionReader.MatchingBranch(writerBranch);
+                    if (readerBranch == -1)
+                    {
+                        lookup[i] = (r, d) => { throw new AvroException( "No \
matching schema for " + writerBranch + " in " + unionReader ); }; +                   \
} +                    else
+                    {
+                        lookup[i] = ResolveReader(writerBranch, \
unionReader[readerBranch]); +                    }
+                }
+                else
+                {
+                    if (!readerSchema.CanRead(writerBranch))
+                    {
+                        lookup[i] = (r, d) => { throw new AvroException( "Schema \
mismatch Reader: " + ReaderSchema + ", writer: " + WriterSchema ); }; +               \
} +                    else
+                    {
+                        lookup[i] = ResolveReader(writerBranch, readerSchema);
+                    }
+                }
+            }
+
+            return (r, d) => ReadUnion(r, d, lookup);
+        }
+
+        private object ReadUnion(object reuse, Decoder d, ReadItem[] branchLookup)
+        {
+            return branchLookup[d.ReadUnionIndex()](reuse, d);
+        }
+
+        private ReadItem ResolveMap(MapSchema writerSchema, MapSchema readerSchema)
+        {
+            var rs = readerSchema.ValueSchema;
+            var ws = writerSchema.ValueSchema;
+            
+            var reader = ResolveReader(ws, rs);
+            var mapAccess = GetMapAccess(readerSchema);
+
+            return (r,d) => ReadMap(r, d, mapAccess, reader);
+        }
+
+        private object ReadMap(object reuse, Decoder decoder, MapAccess mapAccess, \
ReadItem valueReader) +        {
+            object map = mapAccess.Create(reuse);
+
+            for (int n = (int)decoder.ReadMapStart(); n != 0; n = \
(int)decoder.ReadMapNext()) +            {
+                mapAccess.AddElements(map, n, valueReader, decoder, false);
+            }
+            return map;
+        }
+
+        private ReadItem ResolveArray(ArraySchema writerSchema, ArraySchema \
readerSchema) +        {
+            var itemReader = ResolveReader(writerSchema.ItemSchema, \
readerSchema.ItemSchema); +
+            var arrayAccess = GetArrayAccess(readerSchema);
+            return (r, d) => ReadArray(r, d, arrayAccess, itemReader, \
IsReusable(readerSchema.ItemSchema.Tag)); +        }
+
+        private object ReadArray(object reuse, Decoder decoder, ArrayAccess \
arrayAccess, ReadItem itemReader, bool itemReusable) +        {
+            object array = arrayAccess.Create(reuse);
+            int i = 0;
+            for (int n = (int)decoder.ReadArrayStart(); n != 0; n = \
(int)decoder.ReadArrayNext()) +            {
+                arrayAccess.EnsureSize(ref array, i + n);
+                arrayAccess.AddElements(array, n, i, itemReader, decoder, \
itemReusable); +                i += n;
+            }
+            arrayAccess.Resize(ref array, i);
+            return array;
+        }
+
+        private ReadItem ResolveFixed(FixedSchema writerSchema, FixedSchema \
readerSchema) +        {
+            if (readerSchema.Size != writerSchema.Size)
+            {
+                throw new AvroException("Size mismatch between reader and writer \
fixed schemas. Writer: " + writerSchema + +                    ", reader: " + \
readerSchema); +            }
+            var fixedAccess = GetFixedAccess(readerSchema);
+            return (r, d) => ReadFixed(r, d, fixedAccess);
+        }
+
+        private object ReadFixed(object reuse, Decoder decoder, FixedAccess \
fixedAccess) +        {
+            var fixedrec = fixedAccess.CreateFixed(reuse);
+            decoder.ReadFixed(fixedAccess.GetFixedBuffer(fixedrec));
+            return fixedrec;
+        }
+
+        protected static Schema FindBranch(UnionSchema us, Schema s)
+        {
+            int index = us.MatchingBranch(s);
+            if (index >= 0) return us[index];
+            throw new AvroException("No matching schema for " + s + " in " + us);
+        }
+
+        private object ReadNull(object reuse, Decoder decoder)
+        {
+            decoder.ReadNull();
+            return null;
+        }
+
+        private object ReadBoolean(object reuse, Decoder decoder)
+        {
+            return decoder.ReadBoolean();
+        }
+
+        private ReadItem Read(DecoderRead decoderRead)
+        {
+            return (r, d) => decoderRead(d);
+        }
+
+        private DecoderSkip GetSkip(Schema writerSchema)
+        {
+            switch (writerSchema.Tag)
+            {
+                case Schema.Type.Null:
+                    return d => d.SkipNull();
+                case Schema.Type.Boolean:
+                    return d => d.SkipBoolean();
+                case Schema.Type.Int:
+                    return d => d.SkipInt();
+                case Schema.Type.Long:
+                    return d => d.SkipLong();
+                case Schema.Type.Float:
+                    return d => d.SkipFloat();
+                case Schema.Type.Double:
+                    return d => d.SkipDouble();
+                case Schema.Type.String:
+                    return d => d.SkipString();
+                case Schema.Type.Bytes:
+                    return d => d.SkipBytes();
+                case Schema.Type.Error:
+                case Schema.Type.Record:
+                    var recordSkips = new List<DecoderSkip>();
+                    var recSchema = (RecordSchema)writerSchema;
+                    recSchema.Fields.ForEach(r => \
recordSkips.Add(GetSkip(r.Schema))); +                    return d => \
recordSkips.ForEach(s=>s(d)); +                case Schema.Type.Enumeration:
+                    return d => d.SkipEnum();
+                case Schema.Type.Fixed:
+                    var size = ((FixedSchema)writerSchema).Size;
+                    return d => d.SkipFixed(size);
+                case Schema.Type.Array:
+                    var itemSkip = GetSkip(((ArraySchema)writerSchema).ItemSchema);
+                    return d =>
+                    {
+                        for (long n = d.ReadArrayStart(); n != 0; n = \
d.ReadArrayNext()) +                        {
+                            for (long i = 0; i < n; i++) itemSkip(d);
+                        }
+                    };
+                case Schema.Type.Map:
+                    {
+                        var valueSkip = \
GetSkip(((MapSchema)writerSchema).ValueSchema); +                        return d =>
+                        {
+                            for (long n = d.ReadMapStart(); n != 0; n = \
d.ReadMapNext()) +                            {
+                                for (long i = 0; i < n; i++) { d.SkipString(); \
valueSkip(d); } +                            }
+                        };
+                    }
+                case Schema.Type.Union:
+                    var unionSchema = (UnionSchema)writerSchema;
+                    var lookup = new DecoderSkip[unionSchema.Count];
+                    for (int i = 0; i < unionSchema.Count; i++)
+                    {
+                        lookup[i] = GetSkip( unionSchema[i] );
+                    }
+                    return d => lookup[d.ReadUnionIndex()](d);
+                default:
+                    throw new AvroException("Unknown schema type: " + writerSchema);
+            }
+        }
+
+        /// <summary>
+        /// Indicates if it's possible to reuse an object of the specified type. \
Generally +        /// false for immutable objects like int, long, string, etc but \
may differ between +        /// the Specific and Generic implementations. Used to \
avoid retrieving the existing +        /// value if it's not reusable.
+        /// </summary>
+        protected virtual bool IsReusable(Schema.Type tag)
+        {
+            return true;
+        }
+
+        // interfaces to handle details of working with Specific vs Generic objects
+
+        protected interface RecordAccess
+        {
+            /// <summary>
+            /// Creates a new record object. Derived classes can override this to \
return an object of their choice. +            /// </summary>
+            /// <param name="reuse">If appropriate, will reuse this object instead \
of constructing a new one</param> +            /// <returns></returns>
+            object CreateRecord(object reuse);
+
+            /// <summary>
+            /// Used by the default implementation of ReadRecord() to get the \
existing field of a record object. The derived +            /// classes can override \
this to make their own interpretation of the record object. +            /// \
</summary> +            /// <param name="record">The record object to be probed into. \
This is guaranteed to be one that was returned +            /// by a previous call to \
CreateRecord.</param> +            /// <param name="fieldName">The name of the field \
to probe.</param> +            /// <param name="fieldPos">field number</param>
+            /// <returns>The value of the field, if found. Null otherwise.</returns>
+            object GetField(object record, string fieldName, int fieldPos);
+
+            /// <summary>
+            /// Used by the default implementation of ReadRecord() to add a field to \
a record object. The derived +            /// classes can override this to suit their \
own implementation of the record object. +            /// </summary>
+            /// <param name="record">The record object to be probed into. This is \
guaranteed to be one that was returned +            /// by a previous call to \
CreateRecord.</param> +            /// <param name="fieldName">The name of the field \
to probe.</param> +            /// <param name="fieldPos">field number</param>
+            /// <param name="fieldValue">The value to be added for the field</param>
+            void AddField(object record, string fieldName, int fieldPos, object \
fieldValue); +        }
+
+        protected interface EnumAccess
+        {
+            object CreateEnum(object reuse, int ordinal);
+        }
+
+        protected interface FixedAccess
+        {
+            /// <summary>
+            /// Returns a fixed object.
+            /// </summary>
+            /// <param name="reuse">If appropriate, uses this object instead of \
creating a new one.</param> +            /// <returns>A fixed object with an \
appropriate buffer.</returns> +            object CreateFixed(object reuse);
+
+            /// <summary>
+            /// Returns a buffer of appropriate size to read data into.
+            /// </summary>
+            /// <param name="f">The fixed object. It is guaranteed that this is \
something that has been previously +            /// returned by CreateFixed</param>
+            /// <returns>A byte buffer of fixed's size.</returns>
+            byte[] GetFixedBuffer(object f);
+        }
+
+        protected interface ArrayAccess
+        {
+            /// <summary>
+            /// Creates a new array object. The initial size of the object could be \
anything. +            /// </summary>
+            /// <param name="reuse">If appropriate use this instead of creating a \
new one.</param> +            /// <returns>An object suitable to deserialize an avro \
array</returns> +            object Create(object reuse);
+            
+            /// <summary>
+            /// Hint that the array should be able to handle at least targetSize \
elements. The array +            /// is not required to be resized
+            /// </summary>
+            /// <param name="array">Array object who needs to support targetSize \
elements. This is guaranteed to be somthing returned by +            /// a previous \
call to CreateArray().</param> +            /// <param name="targetSize">The new \
size.</param> +            void EnsureSize(ref object array, int targetSize);
+
+            /// <summary>
+            /// Resizes the array to the new value.
+            /// </summary>
+            /// <param name="array">Array object whose size is required. This is \
guaranteed to be somthing returned by +            /// a previous call to \
CreateArray().</param> +            /// <param name="targetSize">The new \
size.</param> +            void Resize(ref object array, int targetSize);
+
+            void AddElements( object array, int elements, int index, ReadItem \
itemReader, Decoder decoder, bool reuse ); +        }
+
+        protected interface MapAccess
+        {
+            /// <summary>
+            /// Creates a new map object.
+            /// </summary>
+            /// <param name="reuse">If appropriate, use this map object instead of \
creating a new one.</param> +            /// <returns>An empty map object.</returns>
+            object Create(object reuse);
+
+            void AddElements(object map, int elements, ReadItem itemReader, Decoder \
decoder, bool reuse); +        }
+
+        private class SchemaPair
+        {
+            private Schema _writerSchema;
+            private Schema _readerSchema;
+
+            public SchemaPair( Schema writerSchema, Schema readerSchema )
+            {
+                _writerSchema = writerSchema;
+                _readerSchema = readerSchema;
+            }
+
+            protected bool Equals( SchemaPair other )
+            {
+                return Equals( _writerSchema, other._writerSchema ) && Equals( \
_readerSchema, other._readerSchema ); +            }
+
+            public override bool Equals( object obj )
+            {
+                if( ReferenceEquals( null, obj ) ) return false;
+                if( ReferenceEquals( this, obj ) ) return true;
+                if( obj.GetType() != this.GetType() ) return false;
+                return Equals( (SchemaPair) obj );
+            }
+
+            public override int GetHashCode()
+            {
+                unchecked
+                {
+                    return ( ( _writerSchema != null ? _writerSchema.GetHashCode() : \
0 ) * 397 ) ^ ( _readerSchema != null ? _readerSchema.GetHashCode() : 0 ); +          \
} +            }
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs?rev=1540206&view=auto
 ==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs Fri Nov \
8 22:15:02 2013 @@ -0,0 +1,375 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using Encoder = Avro.IO.Encoder;
+
+namespace Avro.Generic
+{
+    /// <summary>
+    /// A general purpose writer of data from avro streams. This writer analyzes the \
writer schema +    /// when constructed so that writes can be more efficient. Once \
constructed, a writer can be reused or shared among threads +    /// to avoid \
incurring more resolution costs. +    /// </summary>
+    public abstract class PreresolvingDatumWriter<T> : DatumWriter<T>
+    {
+        public Schema Schema { get; private set; }
+
+        protected delegate void WriteItem(Object value, Encoder encoder);
+
+        private readonly WriteItem _writer;
+        private readonly ArrayAccess _arrayAccess;
+        private readonly MapAccess _mapAccess;
+
+        private readonly Dictionary<RecordSchema,WriteItem> _recordWriters = new \
Dictionary<RecordSchema,WriteItem>(); +
+        public void Write(T datum, Encoder encoder)
+        {
+            _writer( datum, encoder );
+        }
+
+        protected PreresolvingDatumWriter(Schema schema, ArrayAccess arrayAccess, \
MapAccess mapAccess) +        {
+            Schema = schema;
+            _arrayAccess = arrayAccess;
+            _mapAccess = mapAccess;
+            _writer = ResolveWriter(schema);
+        }
+
+        private WriteItem ResolveWriter( Schema schema )
+        {
+            switch (schema.Tag)
+            {
+                case Schema.Type.Null:
+                    return WriteNull;
+                case Schema.Type.Boolean:
+                    return (v, e) => Write<bool>( v, schema.Tag, e.WriteBoolean );
+                case Schema.Type.Int:
+                    return (v, e) => Write<int>( v, schema.Tag, e.WriteInt );
+                case Schema.Type.Long:
+                    return (v, e) => Write<long>( v, schema.Tag, e.WriteLong );
+                case Schema.Type.Float:
+                    return (v, e) => Write<float>( v, schema.Tag, e.WriteFloat );
+                case Schema.Type.Double:
+                    return (v, e) => Write<double>( v, schema.Tag, e.WriteDouble );
+                case Schema.Type.String:
+                    return (v, e) => Write<string>( v, schema.Tag, e.WriteString );
+                case Schema.Type.Bytes:
+                    return (v, e) => Write<byte[]>( v, schema.Tag, e.WriteBytes );
+                case Schema.Type.Error:
+                case Schema.Type.Record:
+                    return ResolveRecord((RecordSchema) schema);
+                case Schema.Type.Enumeration:
+                    return ResolveEnum(schema as EnumSchema);
+                case Schema.Type.Fixed:
+                    return (v, e) => WriteFixed(schema as FixedSchema, v, e);
+                case Schema.Type.Array:
+                    return ResolveArray((ArraySchema)schema);
+                case Schema.Type.Map:
+                    return ResolveMap((MapSchema)schema);
+                case Schema.Type.Union:
+                    return ResolveUnion((UnionSchema)schema);
+                default:
+                    return (v, e) => error(schema, v);
+            }
+        }
+
+        /// <summary>
+        /// Serializes a "null"
+        /// </summary>
+        /// <param name="value">The object to be serialized using null \
schema</param> +        /// <param name="encoder">The encoder to use while \
serialization</param> +        protected void WriteNull(object value, Encoder \
encoder) +        {
+            if (value != null) throw TypeMismatch(value, "null", "null");
+        }
+
+        /// <summary>
+        /// A generic method to serialize primitive Avro types.
+        /// </summary>
+        /// <typeparam name="S">Type of the C# type to be serialized</typeparam>
+        /// <param name="value">The value to be serialized</param>
+        /// <param name="tag">The schema type tag</param>
+        /// <param name="writer">The writer which should be used to write the given \
type.</param> +        protected void Write<S>(object value, Schema.Type tag, \
Writer<S> writer) +        {
+            if (!(value is S)) throw TypeMismatch(value, tag.ToString(), \
typeof(S).ToString()); +            writer((S)value);
+        }
+
+
+        /// <summary>
+        /// Serialized a record using the given RecordSchema. It uses GetField \
method +        /// to extract the field value from the given object.
+        /// </summary>
+        /// <param name="schema">The RecordSchema to use for serialization</param>
+        private WriteItem ResolveRecord(RecordSchema recordSchema)
+        {
+            WriteItem recordResolver;
+            if (_recordWriters.TryGetValue(recordSchema, out recordResolver))
+            {
+                return recordResolver;
+            }
+            var writeSteps = new RecordFieldWriter[recordSchema.Fields.Count];
+            recordResolver = (v, e) => WriteRecordFields(v, writeSteps, e);
+            
+            _recordWriters.Add(recordSchema, recordResolver);
+
+            int index = 0;
+            foreach (Field field in recordSchema)
+            {
+                var record = new RecordFieldWriter
+                                 {
+                                     WriteField = ResolveWriter(field.Schema),
+                                     Field = field
+                                 };
+                writeSteps[index++] = record;
+            }
+
+            return recordResolver;
+        }
+
+        protected abstract void WriteRecordFields(object record, RecordFieldWriter[] \
writers, Encoder encoder); +
+
+        protected class RecordFieldWriter
+        {
+            public WriteItem WriteField { get; set; }
+            public Field Field { get; set; }
+        }
+
+        protected abstract void EnsureRecordObject(RecordSchema recordSchema, object \
value); +
+        /// <summary>
+        /// Extracts the field value from the given object.
+        /// </summary>
+        /// <param name="value">The record value from which the field needs to be \
extracted</param> +        /// <param name="fieldName">The name of the field in the \
record</param> +        /// <param name="fieldPos">The position of field in the \
record</param> +        /// <returns></returns>
+        protected abstract void WriteField(object record, string fieldName, int \
fieldPos, WriteItem writer, Encoder encoder ); +
+        /// <summary>
+        /// Serializes an enumeration.
+        /// </summary>
+        /// <param name="es">The EnumSchema for serialization</param>
+        protected abstract WriteItem ResolveEnum(EnumSchema es);
+
+        /// <summary>
+        /// Serialized an array. The default implementation calls \
EnsureArrayObject() to ascertain that the +        /// given value is an array. It \
then calls GetArrayLength() and GetArrayElement() +        /// to access the members \
of the array and then serialize them. +        /// </summary>
+        /// <param name="schema">The ArraySchema for serialization</param>
+        /// <param name="value">The value being serialized</param>
+        /// <param name="encoder">The encoder for serialization</param>
+        protected WriteItem ResolveArray(ArraySchema schema)
+        {
+            var itemWriter = ResolveWriter(schema.ItemSchema);
+            return (d,e) => WriteArray(itemWriter, d, e);
+        }
+
+        private void WriteArray(WriteItem itemWriter, object array, Encoder encoder)
+        {
+            _arrayAccess.EnsureArrayObject(array);
+            long l = _arrayAccess.GetArrayLength(array);
+            encoder.WriteArrayStart();
+            encoder.SetItemCount(l);
+            _arrayAccess.WriteArrayValues(array, itemWriter, encoder);
+            encoder.WriteArrayEnd();
+        }
+
+        private WriteItem ResolveMap(MapSchema mapSchema)
+        {
+            var itemWriter = ResolveWriter(mapSchema.ValueSchema);
+            return (v, e) => WriteMap(itemWriter, v, e);
+        }
+
+        /// <summary>
+        /// Serialized a map. The default implementation first ensure that the value \
is indeed a map and then uses +        /// GetMapSize() and GetMapElements() to \
access the contents of the map. +        /// </summary>
+        /// <param name="schema">The MapSchema for serialization</param>
+        /// <param name="value">The value to be serialized</param>
+        /// <param name="encoder">The encoder for serialization</param>
+        protected void WriteMap(WriteItem itemWriter, object value, Encoder encoder)
+        {
+            _mapAccess.EnsureMapObject(value);
+            encoder.WriteMapStart();
+            encoder.SetItemCount(_mapAccess.GetMapSize(value));
+            _mapAccess.WriteMapValues(value, itemWriter, encoder);
+            encoder.WriteMapEnd();
+        }
+
+
+        private WriteItem ResolveUnion(UnionSchema unionSchema)
+        {
+            var branchSchemas = unionSchema.Schemas.ToArray();
+            var branchWriters = new WriteItem[branchSchemas.Length];
+            int branchIndex = 0;
+            foreach (var branch in branchSchemas)
+            {
+                branchWriters[branchIndex++] = ResolveWriter(branch);
+            }
+
+
+            return (v, e) => WriteUnion(unionSchema, branchSchemas, branchWriters, \
v, e); +        }
+
+        /// <summary>
+        /// Resolves the given value against the given UnionSchema and serializes \
the object against +        /// the resolved schema member.
+        /// </summary>
+        /// <param name="us">The UnionSchema to resolve against</param>
+        /// <param name="value">The value to be serialized</param>
+        /// <param name="encoder">The encoder for serialization</param>
+        private void WriteUnion(UnionSchema unionSchema, Schema[] branchSchemas, \
WriteItem[] branchWriters, object value, Encoder encoder) +        {
+            int index = ResolveUnion(unionSchema, branchSchemas, value);
+            encoder.WriteUnionIndex(index);
+            branchWriters[index](value, encoder);
+        }
+
+        /// <summary>
+        /// Finds the branch within the given UnionSchema that matches the given \
object. The default implementation +        /// calls Matches() method in the order \
of branches within the UnionSchema. If nothing matches, throws +        /// an \
exception. +        /// </summary>
+        /// <param name="us">The UnionSchema to resolve against</param>
+        /// <param name="obj">The object that should be used in matching</param>
+        /// <returns></returns>
+        protected int ResolveUnion(UnionSchema us, Schema[] branchSchemas, object \
obj) +        {
+            for (int i = 0; i < branchSchemas.Length; i++)
+            {
+                if (UnionBranchMatches(branchSchemas[i], obj)) return i;
+            }
+            throw new AvroException("Cannot find a match for " + obj.GetType() + " \
in " + us); +        }
+
+        /// <summary>
+        /// Serialized a fixed object. The default implementation requires that the \
value is +        /// a GenericFixed object with an identical schema as es.
+        /// </summary>
+        /// <param name="es">The schema for serialization</param>
+        /// <param name="value">The value to be serialized</param>
+        /// <param name="encoder">The encoder for serialization</param>
+        protected abstract void WriteFixed(FixedSchema es, object value, Encoder \
encoder); +
+        protected static AvroException TypeMismatch(object obj, string schemaType, \
string type) +        {
+            return new AvroException(type + " required to write against " + \
schemaType + " schema but found " + (null == obj ? "null" : obj.GetType().ToString()) \
); +        }
+
+        private void error(Schema schema, Object value)
+        {
+            throw new AvroTypeException("Not a " + schema + ": " + value);
+        }
+
+        protected abstract bool UnionBranchMatches(Schema sc, object obj);
+
+        protected interface EnumAccess
+        {
+            void WriteEnum(object value);
+        }
+
+        protected interface ArrayAccess
+        {
+            /// <summary>
+            /// Checks if the given object is an array. If it is a valid array, this \
function returns normally. Otherwise, +            /// it throws an exception. The \
default implementation checks if the value is an array. +            /// </summary>
+            /// <param name="value"></param>
+            void EnsureArrayObject(object value);
+
+            /// <summary>
+            /// Returns the length of an array. The default implementation requires \
the object +            /// to be an array of objects and returns its length. The \
defaul implementation +            /// gurantees that EnsureArrayObject() has been \
called on the value before this +            /// function is called.
+            /// </summary>
+            /// <param name="value">The object whose array length is \
required</param> +            /// <returns>The array length of the given \
object</returns> +            long GetArrayLength(object value);
+
+            /// <summary>
+            /// Returns the element at the given index from the given array object. \
The default implementation +            /// requires that the value is an object \
array and returns the element in that array. The defaul implementation +            \
/// gurantees that EnsureArrayObject() has been called on the value before this +     \
/// function is called. +            /// </summary>
+            /// <param name="value">The array object</param>
+            /// <param name="index">The index to look for</param>
+            /// <returns>The array element at the index</returns>
+            void WriteArrayValues(object array, WriteItem valueWriter, Encoder \
encoder); +        }
+
+        protected interface MapAccess
+        {
+            /// <summary>
+            /// Checks if the given object is a map. If it is a valid map, this \
function returns normally. Otherwise, +            /// it throws an exception. The \
default implementation checks if the value is an IDictionary<string, object>. +       \
/// </summary> +            /// <param name="value"></param>
+            void EnsureMapObject(object value);
+
+            /// <summary>
+            /// Returns the size of the map object. The default implementation \
gurantees that EnsureMapObject has been +            /// successfully called with the \
given value. The default implementation requires the value +            /// to be an \
IDictionary<string, object> and returns the number of elements in it. +            \
/// </summary> +            /// <param name="value">The map object whose size is \
desired</param> +            /// <returns>The size of the given map object</returns>
+            long GetMapSize(object value);
+
+            /// <summary>
+            /// Returns the contents of the given map object. The default \
implementation guarantees that EnsureMapObject +            /// has been called with \
the given value. The defualt implementation of this method requires that +            \
/// the value is an IDictionary<string, object> and returns its contents. +           \
/// </summary> +            /// <param name="value">The map object whose size is \
desired</param> +            /// <returns>The contents of the given map \
object</returns> +            void WriteMapValues(object map, WriteItem valueWriter, \
Encoder encoder); +        }
+
+        protected class DictionaryMapAccess : MapAccess
+        {
+            public void EnsureMapObject( object value )
+            {
+                if( value == null || !( value is IDictionary ) ) throw TypeMismatch( \
value, "map", "IDictionary" ); +            }
+
+            public long GetMapSize( object value )
+            {
+                return ( (IDictionary) value ).Count;
+            }
+
+            public void WriteMapValues(object map, WriteItem valueWriter, Encoder \
encoder) +            {
+                foreach (DictionaryEntry entry in ((IDictionary)map))
+                {
+                    encoder.StartItem();
+                    encoder.WriteString(entry.Key.ToString());
+                    valueWriter(entry.Value, encoder);
+                }
+            }
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs?rev=1540206&view=auto
 ==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs Fri Nov  8 \
22:15:02 2013 @@ -0,0 +1,232 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+using Avro.Generic;
+using Avro.IO;
+
+namespace Avro.Specific
+{
+    /// PreresolvingDatumReader for reading data to ISpecificRecord classes.
+    /// <see cref="PreresolvingDatumReader{T}">For more information about \
performance considerations for choosing this implementation</see> +    public class \
SpecificDatumReader<T> : PreresolvingDatumReader<T> +    {
+        public SpecificDatumReader(Schema writerSchema, Schema readerSchema) : \
base(writerSchema, readerSchema) +        {
+        }
+
+        protected override bool IsReusable(Schema.Type tag)
+        {
+            switch (tag)
+            {
+                case Schema.Type.Double:
+                case Schema.Type.Boolean:
+                case Schema.Type.Int:
+                case Schema.Type.Long:
+                case Schema.Type.Float:
+                case Schema.Type.Bytes:
+                case Schema.Type.Enumeration:
+                case Schema.Type.String:
+                case Schema.Type.Null:
+                    return false;
+            }
+            return true;
+        }
+
+        protected override ArrayAccess GetArrayAccess(ArraySchema readerSchema)
+        {
+            return new SpecificArrayAccess(readerSchema);
+        }
+
+        protected override EnumAccess GetEnumAccess(EnumSchema readerSchema)
+        {
+            return new SpecificEnumAccess();
+        }
+
+        protected override MapAccess GetMapAccess(MapSchema readerSchema)
+        {
+            return new SpecificMapAccess(readerSchema);
+        }
+
+        protected override RecordAccess GetRecordAccess(RecordSchema readerSchema)
+        {
+            if (readerSchema.Name == null)
+            {
+                // ipc support
+                return new GenericDatumReader<T>.GenericRecordAccess(readerSchema);
+            }
+            return new SpecificRecordAccess(readerSchema);
+        }
+
+        protected override FixedAccess GetFixedAccess(FixedSchema readerSchema)
+        {
+            return new SpecificFixedAccess(readerSchema);
+        }
+
+        private static ObjectCreator.CtorDelegate GetConstructor(string name, \
Schema.Type schemaType) +        {
+            var creator = ObjectCreator.Instance;
+            return creator.GetConstructor(name, schemaType, creator.GetType(name, \
schemaType)); +        }
+
+        private class SpecificEnumAccess : EnumAccess
+        {
+            public object CreateEnum(object reuse, int ordinal)
+            {
+                return ordinal;
+            }
+        }
+
+        private class SpecificRecordAccess : RecordAccess
+        {
+            private ObjectCreator.CtorDelegate objCreator;
+
+            public SpecificRecordAccess(RecordSchema readerSchema)
+            {
+                objCreator = GetConstructor(readerSchema.Fullname, \
Schema.Type.Record); +            }
+
+            public object CreateRecord(object reuse)
+            {
+                return reuse ?? objCreator();
+            }
+
+            public object GetField(object record, string fieldName, int fieldPos)
+            {
+                return ((ISpecificRecord)record).Get(fieldPos);
+            }
+
+            public void AddField(object record, string fieldName, int fieldPos, \
object fieldValue) +            {
+                ((ISpecificRecord)record).Put(fieldPos, fieldValue);
+            }
+        }
+
+        private class SpecificFixedAccess : FixedAccess
+        {
+            private ObjectCreator.CtorDelegate objCreator;
+
+            public SpecificFixedAccess(FixedSchema readerSchema)
+            {
+                objCreator = GetConstructor(readerSchema.Fullname, \
Schema.Type.Fixed); +            }
+
+            public object CreateFixed(object reuse)
+            {
+                return reuse ?? objCreator();
+            }
+
+            public byte[] GetFixedBuffer(object rec)
+            {
+                return ((SpecificFixed) rec).Value;
+            }
+        }
+
+        private class SpecificArrayAccess : ArrayAccess
+        {
+            private ObjectCreator.CtorDelegate objCreator;
+
+            public SpecificArrayAccess(ArraySchema readerSchema)
+            {
+                bool nEnum = false;
+                string type = Avro.CodeGen.getType(readerSchema, false, ref nEnum);
+                type = type.Remove(0, 6);              // remove IList<
+                type = type.Remove(type.Length - 1);   // remove >
+        
+                objCreator = GetConstructor(type, Schema.Type.Array);
+            }
+
+            public object Create(object reuse)
+            {
+                IList array;
+
+                if( reuse != null )
+                {
+                    array = reuse as IList;
+                    if( array == null )
+                        throw new AvroException( "array object does not implement \
non-generic IList" ); +                    // retaining existing behavior where array \
contents aren't reused +                    // TODO: try to reuse contents?
+                    array.Clear();
+                }
+                else
+                    array = objCreator() as IList;
+                return array;
+            }
+
+            public void EnsureSize(ref object array, int targetSize)
+            {
+                // no action needed
+            }
+
+            public void Resize(ref object array, int targetSize)
+            {
+                // no action needed
+            }
+
+            public void AddElements( object array, int elements, int index, ReadItem \
itemReader, Decoder decoder, bool reuse ) +            {
+                var list = (IList)array;
+                for (int i=0; i < elements; i++)
+                {
+                    list.Add( itemReader( null, decoder ) );
+                }
+            }
+        }
+
+        private class SpecificMapAccess : MapAccess
+        {
+            private ObjectCreator.CtorDelegate objCreator;
+
+            public SpecificMapAccess(MapSchema readerSchema)
+            {
+                bool nEnum = false;
+                string type = Avro.CodeGen.getType(readerSchema, false, ref nEnum);
+                type = type.Remove(0, 19);             // remove IDictionary<string,
+                type = type.Remove(type.Length - 1);   // remove >
+        
+                objCreator = GetConstructor(type, Schema.Type.Map);
+            }
+
+            public object Create(object reuse)
+            {
+                IDictionary map;
+                if (reuse != null)
+                {
+                    map = reuse as IDictionary;
+                    if (map == null)
+                        throw new AvroException("map object does not implement \
non-generic IList"); +
+                    map.Clear();
+                }
+                else
+                    map = objCreator() as System.Collections.IDictionary;
+                return map;
+            }
+
+            public void AddElements(object mapObj, int elements, ReadItem \
itemReader, Decoder decoder, bool reuse) +            {
+                var map = ((IDictionary)mapObj);
+                for (int i = 0; i < elements; i++)
+                {
+                    var key = decoder.ReadString();
+                    map[key] = itemReader(null, decoder);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

Added: avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs?rev=1540206&view=auto
 ==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs Fri Nov  8 \
22:15:02 2013 @@ -0,0 +1,172 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Avro.Generic;
+using Encoder = Avro.IO.Encoder;
+
+namespace Avro.Specific
+{
+    /// <summary>
+    /// PreresolvingDatumWriter for writing data from ISpecificRecord classes.
+    /// <see cref="PreresolvingDatumWriter{T}">For more information about \
performance considerations for choosing this implementation</see> +    /// </summary>
+    public class SpecificDatumWriter<T> : PreresolvingDatumWriter<T>
+    {
+        public SpecificDatumWriter(Schema schema) : base(schema, new \
SpecificArrayAccess(), new DictionaryMapAccess()) +        {
+        }
+
+        protected override void WriteRecordFields(object recordObj, \
RecordFieldWriter[] writers, Encoder encoder) +        {
+            var record = (ISpecificRecord) recordObj;
+            for (int i = 0; i < writers.Length; i++)
+            {
+                var writer = writers[i];
+                writer.WriteField(record.Get(writer.Field.Pos), encoder);
+            }
+        }
+
+        protected override void EnsureRecordObject(RecordSchema recordSchema, object \
value) +        {
+            if (!(value is ISpecificRecord))
+                throw new AvroTypeException("Record object is not derived from \
ISpecificRecord"); +        }
+
+        protected override void WriteField(object record, string fieldName, int \
fieldPos, WriteItem writer, Encoder encoder) +        {
+            writer(((ISpecificRecord)record).Get(fieldPos), encoder);
+        }
+
+        protected override WriteItem ResolveEnum(EnumSchema es)
+        {
+            var type = ObjectCreator.Instance.GetType(es);
+            
+            var enumNames = Enum.GetNames(type);
+            var translator = new int[enumNames.Length];
+            for(int i = 0; i < enumNames.Length; i++)
+            {
+                if(es.Contains(enumNames[i]))
+                {
+                    translator[i] = es.Ordinal(enumNames[i]);
+                }
+                else
+                {
+                    translator[i] = -1;
+                }
+            }
+
+            return (v,e) =>
+                       {
+                           if(v == null)
+                                throw new AvroTypeException("value is null in \
SpecificDefaultWriter.WriteEnum"); +                           if(v.GetType() == \
type) +                           {
+                               int translated = translator[(int)v];
+                               if (translated == -1)
+                               {
+                                   throw new AvroTypeException("Unknown enum value:" \
+ v.ToString());    +                               }
+                               else
+                               {
+                                   e.WriteEnum(translated);
+                               }
+                           }
+                           else
+                           {
+                               e.WriteEnum(es.Ordinal(v.ToString()));
+                           }
+                       };
+        }
+
+        protected override void WriteFixed(FixedSchema schema, object value, Encoder \
encoder) +        {
+            var fixedrec = value as SpecificFixed;
+            if (fixedrec == null)
+                throw new AvroTypeException("Fixed object is not derived from \
SpecificFixed"); +
+            encoder.WriteFixed(fixedrec.Value);
+        }
+
+        protected override bool UnionBranchMatches( Schema sc, object obj )
+        {
+            if (obj == null && sc.Tag != Avro.Schema.Type.Null) return false;
+            switch (sc.Tag)
+            {
+                case Schema.Type.Null:
+                    return obj == null;
+                case Schema.Type.Boolean:
+                    return obj is bool;
+                case Schema.Type.Int:
+                    return obj is int;
+                case Schema.Type.Long:
+                    return obj is long;
+                case Schema.Type.Float:
+                    return obj is float;
+                case Schema.Type.Double:
+                    return obj is double;
+                case Schema.Type.Bytes:
+                    return obj is byte[];
+                case Schema.Type.String:
+                    return obj is string;
+                case Schema.Type.Error:
+                case Schema.Type.Record:
+                    return obj is ISpecificRecord && 
+                           (((obj as ISpecificRecord).Schema) as \
RecordSchema).SchemaName.Equals((sc as RecordSchema).SchemaName); +                \
case Schema.Type.Enumeration: +                    return obj.GetType().IsEnum && (sc \
as EnumSchema).Symbols.Contains(obj.ToString()); +                case \
Schema.Type.Array: +                    return obj is System.Collections.IList;
+                case Schema.Type.Map:
+                    return obj is System.Collections.IDictionary;
+                case Schema.Type.Union:
+                    return false;   // Union directly within another union not \
allowed! +                case Schema.Type.Fixed:
+                    return obj is SpecificFixed && 
+                           (((obj as SpecificFixed).Schema) as \
FixedSchema).SchemaName.Equals((sc as FixedSchema).SchemaName); +                \
default: +                    throw new AvroException("Unknown schema type: " + \
sc.Tag); +            }
+        }
+
+        class SpecificArrayAccess : ArrayAccess
+        {
+            public void EnsureArrayObject( object value )
+            {
+                if( !( value is System.Collections.IList ) )
+                {
+                    throw new AvroTypeException( "Array does not implement \
non-generic IList" ); +                }
+            }
+
+            public long GetArrayLength(object value)
+            {
+                return ((IList)value).Count;
+            }
+
+            public void WriteArrayValues(object array, WriteItem valueWriter, \
Encoder encoder) +            {
+                var list = (IList) array;
+                for (int i = 0; i < list.Count; i++ )
+                {
+                    valueWriter(list[i], encoder);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

Added: avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj?rev=1540206&view=auto
 ==============================================================================
--- avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj (added)
+++ avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj Fri Nov  8 22:15:02 2013
@@ -0,0 +1,141 @@
+ï » ¿<?xml version="1.0" encoding="utf-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<Project ToolsVersion="4.0" DefaultTargets="Build" \
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{AC4E1909-2594-4D01-9B2B-B832C07BAFE5}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Avro.perf</RootNamespace>
+    <AssemblyName>Avro.perf</AssemblyName>
+    <TargetFrameworkVersion Condition=" '$(TargetFrameworkVersion)' == '' \
">v4.0</TargetFrameworkVersion> +    <FileAlignment>512</FileAlignment>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\build\perf\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\build\perf\Release\</OutputPath>
+    <DefineConstants>
+    </DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Castle.Core, Version=3.2.0.0, Culture=neutral, \
PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"> +      \
<SpecificVersion>False</SpecificVersion> +      \
<HintPath>..\..\..\..\..\lang\csharp\lib\main\Castle.Core.dll</HintPath> +    \
</Reference> +    <Reference Include="nunit.framework, Version=2.5.7.10213, \
Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL"> +      \
<SpecificVersion>False</SpecificVersion> +      \
<HintPath>..\..\..\lib\test\nunit.framework.dll</HintPath> +    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\ipc\Avro.ipc.csproj">
+      <Project>{3b05043a-dc6c-49b6-85bf-9ab055d0b414}</Project>
+      <Name>Avro.ipc</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\main\Avro.main.csproj">
+      <Project>{A0A5CA3C-F58C-4D07-98B0-2C7B62AB20F0}</Project>
+      <Name>Avro.main</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include=".NETFramework,Version=v3.5">
+      <Visible>False</Visible>
+      <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="com\foo\A.cs" />
+    <Compile Include="com\foo\Complex.cs" />
+    <Compile Include="com\foo\MyEnum.cs" />
+    <Compile Include="com\foo\MyFixed.cs" />
+    <Compile Include="com\foo\Narrow.cs" />
+    <Compile Include="com\foo\newRec.cs" />
+    <Compile Include="com\foo\Simple.cs" />
+    <Compile Include="com\foo\Wide.cs" />
+    <Compile Include="PerfTest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="schema.avsc" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- 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">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic