First pass at interface breakup
diff --git a/src/ProtoGen/UmbrellaClassGenerator.cs b/src/ProtoGen/UmbrellaClassGenerator.cs
index cdc275c..6f98704 100644
--- a/src/ProtoGen/UmbrellaClassGenerator.cs
+++ b/src/ProtoGen/UmbrellaClassGenerator.cs
@@ -74,10 +74,6 @@
       return false;
     }
 
-    public string UmbrellaClassName {
-      get { throw new NotImplementedException(); }
-    }
-
     public void Generate(TextGenerator writer) {
       WriteIntroduction(writer);
       WriteExtensionRegistration(writer);
diff --git a/src/ProtocolBuffers.sln b/src/ProtocolBuffers.sln
index 3ad5dc2..50d4375 100644
--- a/src/ProtocolBuffers.sln
+++ b/src/ProtocolBuffers.sln
@@ -25,6 +25,8 @@
 		..\todo.txt = ..\todo.txt
 	EndProjectSection
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolBuffersLite", "ProtocolBuffers\ProtocolBuffersLite.csproj", "{6969BDCE-D925-43F3-94AC-A531E6DF2591}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -80,6 +82,12 @@
 		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.Build.0 = Release|Any CPU
 		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Silverlight2|Any CPU.ActiveCfg = Silverlight2|Any CPU
 		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Silverlight2|Any CPU.Build.0 = Silverlight2|Any CPU
+		{6969BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6969BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6969BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6969BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6969BDCE-D925-43F3-94AC-A531E6DF2591}.Silverlight2|Any CPU.ActiveCfg = Silverlight2|Any CPU
+		{6969BDCE-D925-43F3-94AC-A531E6DF2591}.Silverlight2|Any CPU.Build.0 = Silverlight2|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/src/ProtocolBuffers/AbstractBuilder.cs b/src/ProtocolBuffers/AbstractBuilder.cs
index a60ff0a..2ba9855 100644
--- a/src/ProtocolBuffers/AbstractBuilder.cs
+++ b/src/ProtocolBuffers/AbstractBuilder.cs
@@ -88,7 +88,7 @@
       return MergeFrom(input);
     }
 
-    public IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
+    public IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistryLite registry) {
       return MergeFrom(input, registry);
     }
 
@@ -96,7 +96,7 @@
       return MergeFrom(data);
     }
 
-    public IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
+    public IBuilder WeakMergeFrom(ByteString data, ExtensionRegistryLite registry) {
       return MergeFrom(data, registry);
     }
 
@@ -173,6 +173,10 @@
     }
 
     public virtual TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
+      return MergeFrom(input, (ExtensionRegistryLite)extensionRegistry);
+    }
+
+    public virtual TBuilder MergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) {
       UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
       unknownFields.MergeFrom(input, extensionRegistry, this);
       UnknownFields = unknownFields.Build();
@@ -194,6 +198,10 @@
     }
 
     public virtual TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
+      return MergeFrom(data, (ExtensionRegistryLite)extensionRegistry);
+    }
+
+    public virtual TBuilder MergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry) {
       CodedInputStream input = data.CreateCodedInput();
       MergeFrom(input, extensionRegistry);
       input.CheckLastTagWas(0);
@@ -208,6 +216,10 @@
     }
 
     public virtual TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
+      return MergeFrom(data, (ExtensionRegistryLite)extensionRegistry);
+    }
+
+    public virtual TBuilder MergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry) {
       CodedInputStream input = CodedInputStream.CreateInstance(data);
       MergeFrom(input, extensionRegistry);
       input.CheckLastTagWas(0);
@@ -222,6 +234,10 @@
     }
 
     public virtual TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
+      return MergeFrom(input, (ExtensionRegistryLite)extensionRegistry);
+    }
+
+    public virtual TBuilder MergeFrom(Stream input, ExtensionRegistryLite extensionRegistry) {
       CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
       MergeFrom(codedInput, extensionRegistry);
       codedInput.CheckLastTagWas(0);
@@ -229,6 +245,10 @@
     }
 
     public TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry) {
+      return MergeDelimitedFrom(input, (ExtensionRegistryLite)extensionRegistry);
+    }
+
+    public TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistryLite extensionRegistry) {
       int size = (int) CodedInputStream.ReadRawVarint32(input);
       Stream limitedStream = new LimitedInputStream(input, size);
       return MergeFrom(limitedStream, extensionRegistry);
@@ -279,15 +299,15 @@
       }
 
       public override long Length {
-        get { throw new NotImplementedException(); }
+        get { throw new NotSupportedException(); }
       }
 
       public override long Position {
         get {
-          throw new NotImplementedException();
+          throw new NotSupportedException();
         }
         set {
-          throw new NotImplementedException();
+          throw new NotSupportedException();
         }
       }
 
@@ -301,16 +321,60 @@
       }
 
       public override long Seek(long offset, SeekOrigin origin) {
-        throw new NotImplementedException();
+        throw new NotSupportedException();
       }
 
       public override void SetLength(long value) {
-        throw new NotImplementedException();
+        throw new NotSupportedException();
       }
 
       public override void Write(byte[] buffer, int offset, int count) {
-        throw new NotImplementedException();
+        throw new NotSupportedException();
       }
     }
+
+    IBuilderLite IBuilderLite.WeakClear() {
+      return WeakClear();
+    }
+
+    public IBuilderLite WeakMergeFrom(IMessageLite message) {
+      return MergeFrom(message);
+    }
+
+    IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data) {
+      return WeakMergeFrom(data); 
+    }
+
+    IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistryLite registry) {
+      throw new NotImplementedException();
+    }
+
+    IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input) {
+      return WeakMergeFrom(input);
+    }
+
+    IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input, ExtensionRegistryLite registry) {
+      throw new NotImplementedException();
+    }
+
+    IMessageLite IBuilderLite.WeakBuild() {
+      return WeakBuild(); 
+    }
+
+    IMessageLite IBuilderLite.WeakBuildPartial() {
+      return WeakBuildPartial(); 
+    }
+
+    IBuilderLite IBuilderLite.WeakClone() {
+      return WeakClone(); 
+    }
+
+    IMessageLite IBuilderLite.WeakDefaultInstanceForType {
+      get { return WeakDefaultInstanceForType; }
+    }
+
+    public TBuilder MergeFrom(IMessageLite other) {
+      throw new NotImplementedException();
+    }
   }
 }
diff --git a/src/ProtocolBuffers/AbstractMessage.cs b/src/ProtocolBuffers/AbstractMessage.cs
index 086aac8..9cb38c3 100644
--- a/src/ProtocolBuffers/AbstractMessage.cs
+++ b/src/ProtocolBuffers/AbstractMessage.cs
@@ -72,6 +72,10 @@
       return ToBuilder();
     }
 
+    IMessageLite IMessageLite.WeakDefaultInstanceForType {
+      get { return DefaultInstanceForType; }
+    }
+
     public IMessage WeakDefaultInstanceForType {
       get { return DefaultInstanceForType; }
     }
@@ -233,5 +237,12 @@
       hash = (29 * hash) + UnknownFields.GetHashCode();
       return hash;
     }
+
+    IBuilderLite IMessageLite.WeakCreateBuilderForType() {
+      return WeakCreateBuilderForType(); }
+
+    IBuilderLite IMessageLite.WeakToBuilder() {
+      return WeakToBuilder();
+    }
   }
 }
diff --git a/src/ProtocolBuffers/CodedInputStream.cs b/src/ProtocolBuffers/CodedInputStream.cs
index 3306f30..9173423 100644
--- a/src/ProtocolBuffers/CodedInputStream.cs
+++ b/src/ProtocolBuffers/CodedInputStream.cs
@@ -36,7 +36,9 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Text;
+#if !LITE
 using Google.ProtocolBuffers.Descriptors;
+#endif
 
 namespace Google.ProtocolBuffers {
 
@@ -258,8 +260,8 @@
     /// <summary>
     /// Reads a group field value from the stream.
     /// </summary>    
-    public void ReadGroup(int fieldNumber, IBuilder builder,
-                          ExtensionRegistry extensionRegistry) {
+    public void ReadGroup(int fieldNumber, IBuilderLite builder,
+                          ExtensionRegistryLite extensionRegistry) {
       if (recursionDepth >= recursionLimit) {
         throw InvalidProtocolBufferException.RecursionLimitExceeded();
       }
@@ -273,12 +275,14 @@
     /// Reads a group field value from the stream and merges it into the given
     /// UnknownFieldSet.
     /// </summary>   
-    public void ReadUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder) {
+    [Obsolete]
+    public void ReadUnknownGroup(int fieldNumber, IBuilderLite builder)
+    {
       if (recursionDepth >= recursionLimit) {
         throw InvalidProtocolBufferException.RecursionLimitExceeded();
       }
       ++recursionDepth;
-      builder.MergeFrom(this);
+      builder.WeakMergeFrom(this);
       CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
       --recursionDepth;
     }
@@ -286,7 +290,7 @@
     /// <summary>
     /// Reads an embedded message field value from the stream.
     /// </summary>   
-    public void ReadMessage(IBuilder builder, ExtensionRegistry extensionRegistry) {
+    public void ReadMessage(IBuilderLite builder, ExtensionRegistryLite extensionRegistry) {
       int length = (int) ReadRawVarint32();
       if (recursionDepth >= recursionLimit) {
         throw InvalidProtocolBufferException.RecursionLimitExceeded();
@@ -359,7 +363,7 @@
     public long ReadSInt64() {
       return DecodeZigZag64(ReadRawVarint64());
     }
-
+#if !LITE
     /// <summary>
     /// Reads a field of any primitive type. Enums, groups and embedded
     /// messages are not handled by this method.
@@ -393,7 +397,7 @@
           throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
       }
     }
-
+#endif
     #endregion
 
     #region Underlying reading primitives
diff --git a/src/ProtocolBuffers/CodedOutputStream.cs b/src/ProtocolBuffers/CodedOutputStream.cs
index a7e1eca..b261375 100644
--- a/src/ProtocolBuffers/CodedOutputStream.cs
+++ b/src/ProtocolBuffers/CodedOutputStream.cs
@@ -35,8 +35,9 @@
 using System;
 using System.IO;
 using System.Text;
+#if !LITE
 using Google.ProtocolBuffers.Descriptors;
-
+#endif
 namespace Google.ProtocolBuffers {
 
   /// <summary>
@@ -206,19 +207,20 @@
     /// <summary>
     /// Writes a group field value, including tag, to the stream.
     /// </summary>
-    public void WriteGroup(int fieldNumber, IMessage value) {
+    public void WriteGroup(int fieldNumber, IMessageLite value) {
       WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
       value.WriteTo(this);
       WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
     }
 
-    public void WriteUnknownGroup(int fieldNumber, UnknownFieldSet value) {
+    [Obsolete]
+    public void WriteUnknownGroup(int fieldNumber, IMessageLite value) {
       WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
       value.WriteTo(this);
       WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
     }
 
-    public void WriteMessage(int fieldNumber, IMessage value) {
+    public void WriteMessage(int fieldNumber, IMessageLite value) {
       WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
       WriteRawVarint32((uint)value.SerializedSize);
       value.WriteTo(this);
@@ -263,7 +265,7 @@
       WriteRawVarint64(EncodeZigZag64(value));
     }
 
-    public void WriteMessageSetExtension(int fieldNumber, IMessage value) {
+    public void WriteMessageSetExtension(int fieldNumber, IMessageLite value) {
       WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
       WriteUInt32(WireFormat.MessageSetField.TypeID, (uint)fieldNumber);
       WriteMessage(WireFormat.MessageSetField.Message, value);
@@ -277,6 +279,7 @@
       WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
     }
 
+#if !LITE
     public void WriteField(FieldType fieldType, int fieldNumber, object value) {
       switch (fieldType) {
         case FieldType.Double: WriteDouble(fieldNumber, (double)value); break;
@@ -324,6 +327,7 @@
           break;
       }
     }
+#endif
     #endregion
 
     #region Writing of values without tags
@@ -420,11 +424,11 @@
     /// <summary>
     /// Writes a group field value, without a tag, to the stream.
     /// </summary>
-    public void WriteGroupNoTag(IMessage value) {
+    public void WriteGroupNoTag(IMessageLite value) {
       value.WriteTo(this);
     }
 
-    public void WriteMessageNoTag(IMessage value) {
+    public void WriteMessageNoTag(IMessageLite value) {
       WriteRawVarint32((uint)value.SerializedSize);
       value.WriteTo(this);
     }
@@ -685,7 +689,7 @@
     /// Compute the number of bytes that would be needed to encode a
     /// group field, including the tag.
     /// </summary>
-    public static int ComputeGroupSize(int fieldNumber, IMessage value) {
+    public static int ComputeGroupSize(int fieldNumber, IMessageLite value) {
       return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize;
     }
 
@@ -693,8 +697,9 @@
     /// Compute the number of bytes that would be needed to encode a
     /// group field represented by an UnknownFieldSet, including the tag.
     /// </summary>
+    [Obsolete]
     public static int ComputeUnknownGroupSize(int fieldNumber,
-                                              UnknownFieldSet value) {
+                                              IMessageLite value) {
       return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize;
     }
 
@@ -702,7 +707,7 @@
     /// Compute the number of bytes that would be needed to encode an
     /// embedded message field, including the tag.
     /// </summary>
-    public static int ComputeMessageSize(int fieldNumber, IMessage value) {
+    public static int ComputeMessageSize(int fieldNumber, IMessageLite value) {
       int size = value.SerializedSize;
       return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)size) + size;
     }
@@ -853,7 +858,7 @@
     /// Compute the number of bytes that would be needed to encode a
     /// group field, including the tag.
     /// </summary>
-    public static int ComputeGroupSizeNoTag(IMessage value) {
+    public static int ComputeGroupSizeNoTag(IMessageLite value) {
       return value.SerializedSize;
     }
 
@@ -861,7 +866,8 @@
     /// Compute the number of bytes that would be needed to encode a
     /// group field represented by an UnknownFieldSet, including the tag.
     /// </summary>
-    public static int ComputeUnknownGroupSizeNoTag(UnknownFieldSet value) {
+    [Obsolete]
+    public static int ComputeUnknownGroupSizeNoTag(IMessageLite value) {
       return value.SerializedSize;
     }
 
@@ -869,7 +875,7 @@
     /// Compute the number of bytes that would be needed to encode an
     /// embedded message field, including the tag.
     /// </summary>
-    public static int ComputeMessageSizeNoTag(IMessage value) {
+    public static int ComputeMessageSizeNoTag(IMessageLite value) {
       int size = value.SerializedSize;
       return ComputeRawVarint32Size((uint)size) + size;
     }
@@ -943,7 +949,7 @@
     /// MessageSet extension to the stream. For historical reasons,
     /// the wire format differs from normal fields.
     /// </summary>
-    public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessage value) {
+    public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessageLite value) {
       return ComputeTagSize(WireFormat.MessageSetField.Item) * 2 +
              ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) +
              ComputeMessageSize(WireFormat.MessageSetField.Message, value);
@@ -989,6 +995,7 @@
       return 10;
     }
 
+#if !LITE
     /// <summary>
     /// Compute the number of bytes that would be needed to encode a
     /// field of arbitrary type, including the tag, to the stream.
@@ -1046,6 +1053,7 @@
           throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
       }
     }
+#endif
 
     /// <summary>
     /// Compute the number of bytes that would be needed to encode a tag.
diff --git a/src/ProtocolBuffers/DynamicMessage.cs b/src/ProtocolBuffers/DynamicMessage.cs
index 12f2186..0653fcf 100644
--- a/src/ProtocolBuffers/DynamicMessage.cs
+++ b/src/ProtocolBuffers/DynamicMessage.cs
@@ -338,7 +338,7 @@
           get { return fields.IsInitializedWithRespectTo(type); }
       }
 
-      public override Builder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) {
         UnknownFieldSet.Builder unknownFieldsBuilder = UnknownFieldSet.CreateBuilder(unknownFields);
         unknownFieldsBuilder.MergeFrom(input, extensionRegistry, this);
         unknownFields = unknownFieldsBuilder.Build();
diff --git a/src/ProtocolBuffers/ExtensionInfo.cs b/src/ProtocolBuffers/ExtensionInfo.cs
index 4c877ab..43dd515 100644
--- a/src/ProtocolBuffers/ExtensionInfo.cs
+++ b/src/ProtocolBuffers/ExtensionInfo.cs
@@ -36,7 +36,7 @@
 
 namespace Google.ProtocolBuffers
 {
-  public sealed class ExtensionInfo {
+  public sealed class ExtensionInfo : IGeneratedExtensionLite {
     /// <summary>
     /// The extension's descriptor
     /// </summary>
@@ -55,5 +55,21 @@
       Descriptor = descriptor;
       DefaultInstance = defaultInstance;
     }
+
+    #region IGeneratedExtensionLite Members
+
+    int IGeneratedExtensionLite.Number {
+      get { return Descriptor.FieldNumber; }
+    }
+
+    object IGeneratedExtensionLite.ContainingType {
+      get { return Descriptor; }
+    }
+
+    IMessageLite IGeneratedExtensionLite.MessageDefaultInstance {
+      get { return DefaultInstance; }
+    }
+
+    #endregion
   }
 }
\ No newline at end of file
diff --git a/src/ProtocolBuffers/ExtensionRegistry.cs b/src/ProtocolBuffers/ExtensionRegistry.cs
index 154b690..02cd463 100644
--- a/src/ProtocolBuffers/ExtensionRegistry.cs
+++ b/src/ProtocolBuffers/ExtensionRegistry.cs
@@ -88,41 +88,38 @@
   /// could take advantage of this to inject a mutable object into a message
   /// belonging to privileged code and create mischief.</para>
   /// </remarks>
-  public sealed class ExtensionRegistry {
+  public sealed class ExtensionRegistry : ExtensionRegistryLite {
 
     private static readonly ExtensionRegistry empty = new ExtensionRegistry(
         new Dictionary<string, ExtensionInfo>(),
-        new Dictionary<DescriptorIntPair, ExtensionInfo>(),
+        new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(),
         true);
 
     private readonly IDictionary<string, ExtensionInfo> extensionsByName;
-    private readonly IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
-    private readonly bool readOnly;
 
     private ExtensionRegistry(IDictionary<String, ExtensionInfo> extensionsByName,
-        IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber,
-        bool readOnly) {
+        IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber,
+        bool readOnly)
+      : base(extensionsByNumber, readOnly) {
       this.extensionsByName = extensionsByName;
-      this.extensionsByNumber = extensionsByNumber;
-      this.readOnly = readOnly;
     }
 
     /// <summary>
     /// Construct a new, empty instance.
     /// </summary>
-    public static ExtensionRegistry CreateInstance() {
+    public static new ExtensionRegistry CreateInstance() {
       return new ExtensionRegistry(new Dictionary<string, ExtensionInfo>(),
-        new Dictionary<DescriptorIntPair, ExtensionInfo>(), false);
+        new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(), false);
     }
 
     /// <summary>
     /// Get the unmodifiable singleton empty instance.
     /// </summary>
-    public static ExtensionRegistry Empty {
+    public new static ExtensionRegistry Empty {
       get { return empty; }
     }
 
-    public ExtensionRegistry AsReadOnly() {
+    public override ExtensionRegistryLite AsReadOnly() {
       return new ExtensionRegistry(extensionsByName, extensionsByNumber, true);
     }
 
@@ -146,9 +143,9 @@
     /// </summary>
     public ExtensionInfo this[MessageDescriptor containingType, int fieldNumber] {
       get {
-        ExtensionInfo ret;
-        extensionsByNumber.TryGetValue(new DescriptorIntPair(containingType, fieldNumber), out ret);
-        return ret;
+        IGeneratedExtensionLite ret;
+        extensionsByNumber.TryGetValue(new ExtensionIntPair(containingType, fieldNumber), out ret);
+        return ret as ExtensionInfo;
       }
     }
 
@@ -198,7 +195,7 @@
       }
 
       extensionsByName[extension.Descriptor.FullName] = extension;
-      extensionsByNumber[new DescriptorIntPair(extension.Descriptor.ContainingType,
+      extensionsByNumber[new ExtensionIntPair(extension.Descriptor.ContainingType,
           extension.Descriptor.FieldNumber)] = extension;
 
       FieldDescriptor field = extension.Descriptor;
@@ -212,34 +209,5 @@
         extensionsByName[field.MessageType.FullName] = extension;
       }
     }
-
-    /// <summary>
-    /// Nested type just used to represent a pair of MessageDescriptor and int, as
-    /// the key into the "by number" map.
-    /// </summary>
-    private struct DescriptorIntPair : IEquatable<DescriptorIntPair> {
-      readonly MessageDescriptor descriptor;
-      readonly int number;
-
-      internal DescriptorIntPair(MessageDescriptor descriptor, int number) {
-        this.descriptor = descriptor;
-        this.number = number;
-      }
-
-      public override int GetHashCode() {
-        return descriptor.GetHashCode() * ((1 << 16) - 1) + number;
-      }
-
-      public override bool Equals(object obj) {
-        if (!(obj is DescriptorIntPair)) {
-          return false;
-        }
-        return Equals((DescriptorIntPair)obj);
-      }
-
-      public bool Equals(DescriptorIntPair other) {
-        return descriptor == other.descriptor && number == other.number;
-      }
-    }
   }
 }
diff --git a/src/ProtocolBuffers/ExtensionRegistryLite.cs b/src/ProtocolBuffers/ExtensionRegistryLite.cs
index 154b690..693aeb2 100644
--- a/src/ProtocolBuffers/ExtensionRegistryLite.cs
+++ b/src/ProtocolBuffers/ExtensionRegistryLite.cs
@@ -33,14 +33,15 @@
 #endregion
 
 using System.Collections.Generic;
-using Google.ProtocolBuffers.Descriptors;
 using System;
 
 namespace Google.ProtocolBuffers {
+
+
   /// <summary>
   /// A table of known extensions, searchable by name or field number.  When
   /// parsing a protocol message that might have extensions, you must provide
-  /// an <see cref="ExtensionRegistry"/> in which you have registered any extensions
+  /// an <see cref="ExtensionRegistryLite"/> in which you have registered any extensions
   /// that you want to be able to parse.  Otherwise, those extensions will just
   /// be treated like unknown fields.
   /// </summary>
@@ -61,7 +62,7 @@
   /// Then you might write code like:
   ///
   /// <code>
-  /// ExtensionRegistry registry = ExtensionRegistry.CreateInstance();
+  /// ExtensionRegistryLite registry = ExtensionRegistryLite.CreateInstance();
   /// registry.Add(MyProto.Bar);
   /// MyProto.Foo message = MyProto.Foo.ParseFrom(input, registry);
   /// </code>
@@ -88,21 +89,17 @@
   /// could take advantage of this to inject a mutable object into a message
   /// belonging to privileged code and create mischief.</para>
   /// </remarks>
-  public sealed class ExtensionRegistry {
+  public class ExtensionRegistryLite {
 
-    private static readonly ExtensionRegistry empty = new ExtensionRegistry(
-        new Dictionary<string, ExtensionInfo>(),
-        new Dictionary<DescriptorIntPair, ExtensionInfo>(),
+    private static readonly ExtensionRegistryLite empty = new ExtensionRegistryLite(
+        new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(),
         true);
 
-    private readonly IDictionary<string, ExtensionInfo> extensionsByName;
-    private readonly IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
-    private readonly bool readOnly;
+    protected readonly IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber;
+    protected readonly bool readOnly;
 
-    private ExtensionRegistry(IDictionary<String, ExtensionInfo> extensionsByName,
-        IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber,
+    protected ExtensionRegistryLite(IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber,
         bool readOnly) {
-      this.extensionsByName = extensionsByName;
       this.extensionsByNumber = extensionsByNumber;
       this.readOnly = readOnly;
     }
@@ -110,44 +107,30 @@
     /// <summary>
     /// Construct a new, empty instance.
     /// </summary>
-    public static ExtensionRegistry CreateInstance() {
-      return new ExtensionRegistry(new Dictionary<string, ExtensionInfo>(),
-        new Dictionary<DescriptorIntPair, ExtensionInfo>(), false);
+    public static ExtensionRegistryLite CreateInstance() {
+      return new ExtensionRegistryLite(
+        new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(), false);
     }
 
     /// <summary>
     /// Get the unmodifiable singleton empty instance.
     /// </summary>
-    public static ExtensionRegistry Empty {
+    public static ExtensionRegistryLite Empty {
       get { return empty; }
     }
 
-    public ExtensionRegistry AsReadOnly() {
-      return new ExtensionRegistry(extensionsByName, extensionsByNumber, true);
-    }
-
-    /// <summary>
-    /// Finds an extension by fully-qualified field name, in the
-    /// proto namespace, i.e. result.Descriptor.FullName will match
-    /// <paramref name="fullName"/> if a match is found. A null
-    /// reference is returned if the extension can't be found.
-    /// </summary>
-    public ExtensionInfo this[string fullName] {
-      get {
-        ExtensionInfo ret;
-        extensionsByName.TryGetValue(fullName, out ret);
-        return ret;
-      }
+    public virtual ExtensionRegistryLite AsReadOnly() {
+      return new ExtensionRegistryLite(extensionsByNumber, true);
     }
 
     /// <summary>
     /// Finds an extension by containing type and field number.
     /// A null reference is returned if the extension can't be found.
     /// </summary>
-    public ExtensionInfo this[MessageDescriptor containingType, int fieldNumber] {
+    public IGeneratedExtensionLite this[IMessageLite containingType, int fieldNumber] {
       get {
-        ExtensionInfo ret;
-        extensionsByNumber.TryGetValue(new DescriptorIntPair(containingType, fieldNumber), out ret);
+        IGeneratedExtensionLite ret;
+        extensionsByNumber.TryGetValue(new ExtensionIntPair(containingType, fieldNumber), out ret);
         return ret;
       }
     }
@@ -155,90 +138,41 @@
     /// <summary>
     /// Add an extension from a generated file to the registry.
     /// </summary>
-    public void Add<TExtension> (GeneratedExtensionBase<TExtension> extension) {
-      if (extension.Descriptor.MappedType == MappedType.Message) {
-        Add(new ExtensionInfo(extension.Descriptor, extension.MessageDefaultInstance));
-      } else {
-        Add(new ExtensionInfo(extension.Descriptor, null));
-      }
-    }
-
-    /// <summary>
-    /// Adds a non-message-type extension to the registry by descriptor.
-    /// </summary>
-    /// <param name="type"></param>
-    public void Add(FieldDescriptor type) {
-      if (type.MappedType == MappedType.Message) {
-        throw new ArgumentException("ExtensionRegistry.Add() must be provided a default instance "
-            + "when adding an embedded message extension.");
-      }
-      Add(new ExtensionInfo(type, null));
-    }
-
-    /// <summary>
-    /// Adds a message-type-extension to the registry by descriptor.
-    /// </summary>
-    /// <param name="type"></param>
-    /// <param name="defaultInstance"></param>
-    public void Add(FieldDescriptor type, IMessage defaultInstance) {
-      if (type.MappedType != MappedType.Message) {
-        throw new ArgumentException("ExtensionRegistry.Add() provided a default instance for a "
-            + "non-message extension.");
-      }
-      Add(new ExtensionInfo(type, defaultInstance));
-    }
-
-    private void Add(ExtensionInfo extension) {
+    public virtual void Add(IGeneratedExtensionLite extension) {
       if (readOnly) {
         throw new InvalidOperationException("Cannot add entries to a read-only extension registry");
       }
-      if (!extension.Descriptor.IsExtension) {
-        throw new ArgumentException("ExtensionRegistry.add() was given a FieldDescriptor for a "
-            + "regular (non-extension) field.");
-      }
-
-      extensionsByName[extension.Descriptor.FullName] = extension;
-      extensionsByNumber[new DescriptorIntPair(extension.Descriptor.ContainingType,
-          extension.Descriptor.FieldNumber)] = extension;
-
-      FieldDescriptor field = extension.Descriptor;
-      if (field.ContainingType.Options.MessageSetWireFormat
-          && field.FieldType == FieldType.Message
-          && field.IsOptional
-          && field.ExtensionScope == field.MessageType) {
-        // This is an extension of a MessageSet type defined within the extension
-        // type's own scope. For backwards-compatibility, allow it to be looked
-        // up by type name.
-        extensionsByName[field.MessageType.FullName] = extension;
-      }
+      extensionsByNumber.Add(
+        new ExtensionIntPair(extension.ContainingType, extension.Number),
+        extension);
     }
 
     /// <summary>
     /// Nested type just used to represent a pair of MessageDescriptor and int, as
     /// the key into the "by number" map.
     /// </summary>
-    private struct DescriptorIntPair : IEquatable<DescriptorIntPair> {
-      readonly MessageDescriptor descriptor;
+    protected struct ExtensionIntPair : IEquatable<ExtensionIntPair> {
+      readonly object msgType;
       readonly int number;
 
-      internal DescriptorIntPair(MessageDescriptor descriptor, int number) {
-        this.descriptor = descriptor;
+      internal ExtensionIntPair(object msgType, int number) {
+        this.msgType = msgType;
         this.number = number;
       }
 
       public override int GetHashCode() {
-        return descriptor.GetHashCode() * ((1 << 16) - 1) + number;
+        return msgType.GetHashCode() * ((1 << 16) - 1) + number;
       }
 
       public override bool Equals(object obj) {
-        if (!(obj is DescriptorIntPair)) {
+        if (!(obj is ExtensionIntPair)) {
           return false;
         }
-        return Equals((DescriptorIntPair)obj);
+        return Equals((ExtensionIntPair)obj);
       }
 
-      public bool Equals(DescriptorIntPair other) {
-        return descriptor == other.descriptor && number == other.number;
+      public bool Equals(ExtensionIntPair other) {
+        return msgType.Equals(other.msgType) && number == other.number;
       }
     }
   }
diff --git a/src/ProtocolBuffers/GeneratedExtensionBase.cs b/src/ProtocolBuffers/GeneratedExtensionBase.cs
index 813f69c..9896a46 100644
--- a/src/ProtocolBuffers/GeneratedExtensionBase.cs
+++ b/src/ProtocolBuffers/GeneratedExtensionBase.cs
@@ -39,6 +39,7 @@
 using Google.ProtocolBuffers.Descriptors;
 
 namespace Google.ProtocolBuffers {
+
   /// <summary>
   /// Base type for all generated extensions.
   /// </summary>
@@ -87,6 +88,10 @@
       get { return descriptor; }
     }
 
+    public int Number {
+      get { return Descriptor.FieldNumber; }
+    }
+
     /// <summary>
     /// Returns the default message instance for extensions which are message types.
     /// </summary>
diff --git a/src/ProtocolBuffers/GeneratedExtensionLite.cs b/src/ProtocolBuffers/GeneratedExtensionLite.cs
new file mode 100644
index 0000000..2679451
--- /dev/null
+++ b/src/ProtocolBuffers/GeneratedExtensionLite.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Google.ProtocolBuffers {
+
+  public interface IGeneratedExtensionLite {
+    int Number { get; }
+    object ContainingType { get; }
+    IMessageLite MessageDefaultInstance { get; }
+  }
+
+  public class GeneratedExtensionLite : IGeneratedExtensionLite {
+    public int Number {
+      get { throw new NotImplementedException(); }
+    }
+
+    public object ContainingType {
+      get { throw new NotImplementedException(); }
+    }
+
+    public IMessageLite MessageDefaultInstance {
+      get { throw new NotImplementedException(); }
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/ProtocolBuffers/IBuilder.cs b/src/ProtocolBuffers/IBuilder.cs
index b1aa4fb..f8d828a 100644
--- a/src/ProtocolBuffers/IBuilder.cs
+++ b/src/ProtocolBuffers/IBuilder.cs
@@ -47,12 +47,12 @@
   /// use explicit interface implemenation for the non-generic form. This mirrors
   /// how IEnumerable and IEnumerable&lt;T&gt; work.
   /// </summary>
-  public interface IBuilder {
+  public interface IBuilder : IBuilderLite {
     /// <summary>
     /// Returns true iff all required fields in the message and all
     /// embedded messages are set.
     /// </summary>
-    bool IsInitialized { get; }
+    new bool IsInitialized { get; }
 
     /// <summary>
     /// Only present in the nongeneric interface - useful for tests, but
@@ -119,17 +119,17 @@
 
     #region Methods which are like those of the generic form, but without any knowledge of the type parameters
     IBuilder WeakAddRepeatedField(FieldDescriptor field, object value);
-    IBuilder WeakClear();
+    new IBuilder WeakClear();
     IBuilder WeakClearField(FieldDescriptor field);
     IBuilder WeakMergeFrom(IMessage message);
-    IBuilder WeakMergeFrom(ByteString data);
-    IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry);
-    IBuilder WeakMergeFrom(CodedInputStream input);
-    IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
-    IMessage WeakBuild();
-    IMessage WeakBuildPartial();
-    IBuilder WeakClone();
-    IMessage WeakDefaultInstanceForType { get; }
+    new IBuilder WeakMergeFrom(ByteString data);
+    new IBuilder WeakMergeFrom(ByteString data, ExtensionRegistryLite registry);
+    new IBuilder WeakMergeFrom(CodedInputStream input);
+    new IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistryLite registry);
+    new IMessage WeakBuild();
+    new IMessage WeakBuildPartial();
+    new IBuilder WeakClone();
+    new IMessage WeakDefaultInstanceForType { get; }
     #endregion
   }
 
@@ -139,7 +139,7 @@
   /// </summary>
   /// <typeparam name="TMessage">Type of message</typeparam>
   /// <typeparam name="TBuilder">Type of builder</typeparam>
-  public interface IBuilder<TMessage, TBuilder> : IBuilder
+  public interface IBuilder<TMessage, TBuilder> : IBuilder, IBuilderLite<TMessage, TBuilder>
       where TMessage : IMessage<TMessage, TBuilder> 
       where TBuilder : IBuilder<TMessage, TBuilder> {
 
@@ -148,7 +148,7 @@
     /// <summary>
     /// Resets all fields to their default values.
     /// </summary>
-    TBuilder Clear();
+    new TBuilder Clear();
 
     /// <summary>
     /// Merge the specified other message into the message being
@@ -163,7 +163,7 @@
     /// </summary>
     /// <param name="other"></param>
     /// <returns></returns>
-    TBuilder MergeFrom(TMessage other);
+    new TBuilder MergeFrom(TMessage other);
 
     /// <summary>
     /// Merge the specified other message which may be a different implementation of
@@ -180,19 +180,19 @@
     /// <exception cref="UninitializedMessageException">the message
     /// is missing one or more required fields; use BuildPartial to bypass
     /// this check</exception>
-    TMessage Build();
+    new TMessage Build();
 
     /// <summary>
     /// Like Build(), but does not throw an exception if the message is missing
     /// required fields. Instead, a partial message is returned.
     /// </summary>
-    TMessage BuildPartial();
+    new TMessage BuildPartial();
 
     /// <summary>
     /// Clones this builder.
     /// TODO(jonskeet): Explain depth of clone.
     /// </summary>
-    TBuilder Clone();
+    new TBuilder Clone();
 
     /// <summary>
     /// Parses a message of this type from the input and merges it with this
@@ -213,7 +213,7 @@
     /// Use BuildPartial to build, which ignores missing required fields.
     /// </list>
     /// </remarks>
-    TBuilder MergeFrom(CodedInputStream input);
+    new TBuilder MergeFrom(CodedInputStream input);
 
     /// <summary>
     /// Like MergeFrom(CodedInputStream), but also parses extensions.
@@ -221,13 +221,13 @@
     /// in <paramref name="extensionRegistry"/>. Extensions not in the registry
     /// will be treated as unknown fields.
     /// </summary>
-    TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
+    new TBuilder MergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry);
 
     /// <summary>
     /// Get's the message's type's default instance.
     /// <see cref="IMessage{TMessage}.DefaultInstanceForType" />
     /// </summary>
-    TMessage DefaultInstanceForType { get; }
+    new TMessage DefaultInstanceForType { get; }
 
     /// <summary>
     /// Clears the field. This is exactly equivalent to calling the generated
@@ -258,12 +258,12 @@
     /// write messages in this format.
     /// </summary>
     /// <param name="input"></param>
-    TBuilder MergeDelimitedFrom(Stream input);
+    new TBuilder MergeDelimitedFrom(Stream input);
 
     /// <summary>
     /// Like MergeDelimitedFrom(Stream) but supporting extensions.
     /// </summary>
-    TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry);
+    new TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistryLite extensionRegistry);
 
     #region Convenience methods
     /// <summary>
@@ -271,28 +271,28 @@
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream).
     /// </summary>
-    TBuilder MergeFrom(ByteString data);
+    new TBuilder MergeFrom(ByteString data);
 
     /// <summary>
     /// Parse <paramref name="data"/> as a message of this type and merge
     /// it with the message being built. This is just a small wrapper around
-    /// MergeFrom(CodedInputStream, ExtensionRegistry).
+    /// MergeFrom(CodedInputStream, ExtensionRegistryLite).
     /// </summary>
-    TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
+    new TBuilder MergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry);
 
     /// <summary>
     /// Parse <paramref name="data"/> as a message of this type and merge
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream).
     /// </summary>
-    TBuilder MergeFrom(byte[] data);
+    new TBuilder MergeFrom(byte[] data);
 
     /// <summary>
     /// Parse <paramref name="data"/> as a message of this type and merge
     /// it with the message being built. This is just a small wrapper around
-    /// MergeFrom(CodedInputStream, ExtensionRegistry).
+    /// MergeFrom(CodedInputStream, ExtensionRegistryLite).
     /// </summary>
-    TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
+    new TBuilder MergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry);
 
     /// <summary>
     /// Parse <paramref name="input"/> as a message of this type and merge
@@ -304,14 +304,14 @@
     /// to write your message and MmergeDelimitedFrom(Stream) to read it.
     /// Despite usually reading the entire stream, this method never closes the stream. 
     /// </summary>
-    TBuilder MergeFrom(Stream input);
+    new TBuilder MergeFrom(Stream input);
 
     /// <summary>
     /// Parse <paramref name="input"/> as a message of this type and merge
     /// it with the message being built. This is just a small wrapper around
-    /// MergeFrom(CodedInputStream, ExtensionRegistry).
+    /// MergeFrom(CodedInputStream, ExtensionRegistryLite).
     /// </summary>
-    TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
+    new TBuilder MergeFrom(Stream input, ExtensionRegistryLite extensionRegistry);
     #endregion
   }
 }
diff --git a/src/ProtocolBuffers/IBuilderLite.cs b/src/ProtocolBuffers/IBuilderLite.cs
index b1aa4fb..459d693 100644
--- a/src/ProtocolBuffers/IBuilderLite.cs
+++ b/src/ProtocolBuffers/IBuilderLite.cs
@@ -35,7 +35,6 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
-using Google.ProtocolBuffers.Descriptors;
 
 namespace Google.ProtocolBuffers {
 
@@ -47,90 +46,23 @@
   /// use explicit interface implemenation for the non-generic form. This mirrors
   /// how IEnumerable and IEnumerable&lt;T&gt; work.
   /// </summary>
-  public interface IBuilder {
+  public interface IBuilderLite {
     /// <summary>
     /// Returns true iff all required fields in the message and all
     /// embedded messages are set.
     /// </summary>
     bool IsInitialized { get; }
 
-    /// <summary>
-    /// Only present in the nongeneric interface - useful for tests, but
-    /// not as much in real life.
-    /// </summary>
-    IBuilder SetField(FieldDescriptor field, object value);
-
-    /// <summary>
-    /// Only present in the nongeneric interface - useful for tests, but
-    /// not as much in real life.
-    /// </summary>
-    IBuilder SetRepeatedField(FieldDescriptor field, int index, object value);
-
-    /// <summary>
-    /// Behaves like the equivalent property in IMessage&lt;T&gt;.
-    /// The returned map may or may not reflect future changes to the builder.
-    /// Either way, the returned map is unmodifiable.
-    /// </summary>
-    IDictionary<FieldDescriptor, object> AllFields { get; }
-
-    /// <summary>
-    /// Allows getting and setting of a field.
-    /// <see cref="IMessage{TMessage, TBuilder}.Item(FieldDescriptor)"/>
-    /// </summary>
-    /// <param name="field"></param>
-    /// <returns></returns>
-    object this[FieldDescriptor field] { get; set; }
-
-    /// <summary>
-    /// Get the message's type descriptor.
-    /// <see cref="IMessage{TMessage, TBuilder}.DescriptorForType"/>
-    /// </summary>
-    MessageDescriptor DescriptorForType { get; }
-
-    /// <summary>
-    /// <see cref="IMessage{TMessage, TBuilder}.GetRepeatedFieldCount"/>
-    /// </summary>
-    /// <param name="field"></param>
-    /// <returns></returns>
-    int GetRepeatedFieldCount(FieldDescriptor field);
-
-    /// <summary>
-    /// Allows getting and setting of a repeated field value.
-    /// <see cref="IMessage{TMessage, TBuilder}.Item(FieldDescriptor, int)"/>
-    /// </summary>
-    object this[FieldDescriptor field, int index] { get; set; }
-
-    /// <summary>
-    /// <see cref="IMessage{TMessage, TBuilder}.HasField"/>
-    /// </summary>
-    bool HasField(FieldDescriptor field);
-
-    /// <summary>
-    /// <see cref="IMessage{TMessage, TBuilder}.UnknownFields"/>
-    /// </summary>
-    UnknownFieldSet UnknownFields { get; set; }
-
-    /// <summary>
-    /// Create a builder for messages of the appropriate type for the given field.
-    /// Messages built with this can then be passed to the various mutation properties
-    /// and methods.
-    /// </summary>
-    IBuilder CreateBuilderForField(FieldDescriptor field);
-
-    #region Methods which are like those of the generic form, but without any knowledge of the type parameters
-    IBuilder WeakAddRepeatedField(FieldDescriptor field, object value);
-    IBuilder WeakClear();
-    IBuilder WeakClearField(FieldDescriptor field);
-    IBuilder WeakMergeFrom(IMessage message);
-    IBuilder WeakMergeFrom(ByteString data);
-    IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry);
-    IBuilder WeakMergeFrom(CodedInputStream input);
-    IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
-    IMessage WeakBuild();
-    IMessage WeakBuildPartial();
-    IBuilder WeakClone();
-    IMessage WeakDefaultInstanceForType { get; }
-    #endregion
+    IBuilderLite WeakClear();
+    IBuilderLite WeakMergeFrom(IMessageLite message);
+    IBuilderLite WeakMergeFrom(ByteString data);
+    IBuilderLite WeakMergeFrom(ByteString data, ExtensionRegistryLite registry);
+    IBuilderLite WeakMergeFrom(CodedInputStream input);
+    IBuilderLite WeakMergeFrom(CodedInputStream input, ExtensionRegistryLite registry);
+    IMessageLite WeakBuild();
+    IMessageLite WeakBuildPartial();
+    IBuilderLite WeakClone();
+    IMessageLite WeakDefaultInstanceForType { get; }
   }
 
   /// <summary>
@@ -139,11 +71,9 @@
   /// </summary>
   /// <typeparam name="TMessage">Type of message</typeparam>
   /// <typeparam name="TBuilder">Type of builder</typeparam>
-  public interface IBuilder<TMessage, TBuilder> : IBuilder
-      where TMessage : IMessage<TMessage, TBuilder> 
-      where TBuilder : IBuilder<TMessage, TBuilder> {
-
-    TBuilder SetUnknownFields(UnknownFieldSet unknownFields);
+  public interface IBuilderLite<TMessage, TBuilder> : IBuilderLite
+      where TMessage : IMessageLite<TMessage, TBuilder> 
+      where TBuilder : IBuilderLite<TMessage, TBuilder> {
 
     /// <summary>
     /// Resets all fields to their default values.
@@ -169,7 +99,7 @@
     /// Merge the specified other message which may be a different implementation of
     /// the same message descriptor.
     /// </summary>
-    TBuilder MergeFrom(IMessage other);
+    TBuilder MergeFrom(IMessageLite other);
 
     /// <summary>
     /// Constructs the final message. Once this is called, this Builder instance
@@ -221,37 +151,15 @@
     /// in <paramref name="extensionRegistry"/>. Extensions not in the registry
     /// will be treated as unknown fields.
     /// </summary>
-    TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
+    TBuilder MergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry);
 
     /// <summary>
     /// Get's the message's type's default instance.
-    /// <see cref="IMessage{TMessage}.DefaultInstanceForType" />
+    /// <see cref="IMessageLite{TMessage}.DefaultInstanceForType" />
     /// </summary>
     TMessage DefaultInstanceForType { get; }
 
     /// <summary>
-    /// Clears the field. This is exactly equivalent to calling the generated
-    /// Clear method corresponding to the field.
-    /// </summary>
-    /// <param name="field"></param>
-    /// <returns></returns>
-    TBuilder ClearField(FieldDescriptor field);
-
-    /// <summary>
-    /// Appends the given value as a new element for the specified repeated field.
-    /// </summary>
-    /// <exception cref="ArgumentException">the field is not a repeated field,
-    /// the field does not belong to this builder's type, or the value is
-    /// of the incorrect type
-    /// </exception>
-    TBuilder AddRepeatedField(FieldDescriptor field, object value);
-
-    /// <summary>
-    /// Merge some unknown fields into the set for this message.
-    /// </summary>
-    TBuilder MergeUnknownFields(UnknownFieldSet unknownFields);
-    
-    /// <summary>
     /// Like MergeFrom(Stream), but does not read until the end of the file.
     /// Instead, the size of the message (encoded as a varint) is read first,
     /// then the message data. Use Message.WriteDelimitedTo(Stream) to
@@ -263,7 +171,7 @@
     /// <summary>
     /// Like MergeDelimitedFrom(Stream) but supporting extensions.
     /// </summary>
-    TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry);
+    TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistryLite extensionRegistry);
 
     #region Convenience methods
     /// <summary>
@@ -278,7 +186,7 @@
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream, ExtensionRegistry).
     /// </summary>
-    TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
+    TBuilder MergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry);
 
     /// <summary>
     /// Parse <paramref name="data"/> as a message of this type and merge
@@ -292,7 +200,7 @@
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream, ExtensionRegistry).
     /// </summary>
-    TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
+    TBuilder MergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry);
 
     /// <summary>
     /// Parse <paramref name="input"/> as a message of this type and merge
@@ -311,7 +219,7 @@
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream, ExtensionRegistry).
     /// </summary>
-    TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
+    TBuilder MergeFrom(Stream input, ExtensionRegistryLite extensionRegistry);
     #endregion
   }
 }
diff --git a/src/ProtocolBuffers/IMessage.cs b/src/ProtocolBuffers/IMessage.cs
index ec955c6..4d37a8d 100644
--- a/src/ProtocolBuffers/IMessage.cs
+++ b/src/ProtocolBuffers/IMessage.cs
@@ -43,7 +43,7 @@
   /// Non-generic interface used for all parts of the API which don't require
   /// any type knowledge.
   /// </summary>
-  public interface IMessage {
+  public interface IMessage : IMessageLite {
     /// <summary>
     /// Returns the message's type's descriptor. This differs from the
     /// Descriptor property of each generated message class in that this
@@ -110,7 +110,7 @@
     /// Returns true iff all required fields in the message and all embedded
     /// messages are set.
     /// </summary>
-    bool IsInitialized { get; }
+    new bool IsInitialized { get; }
 
     /// <summary>
     /// Serializes the message and writes it to the given output stream.
@@ -124,7 +124,7 @@
     /// of the message before the data, then making sure you limit the input to
     /// that size when receiving the data. Alternatively, use WriteDelimitedTo(Stream).
     /// </remarks>
-    void WriteTo(CodedOutputStream output);
+    new void WriteTo(CodedOutputStream output);
 
     /// <summary>
     /// Like WriteTo(Stream) but writes the size of the message as a varint before
@@ -134,13 +134,13 @@
     /// YourMessageType.ParseDelimitedFrom(Stream) to parse messages written by this method.
     /// </summary>
     /// <param name="output"></param>
-    void WriteDelimitedTo(Stream output);
+    new void WriteDelimitedTo(Stream output);
 
     /// <summary>
     /// Returns the number of bytes required to encode this message.
     /// The result is only computed on the first call and memoized after that.
     /// </summary>
-    int SerializedSize { get; }
+    new int SerializedSize { get; }
 
     #region Comparison and hashing
     /// <summary>
@@ -149,13 +149,13 @@
     /// (as defined by DescriptorForType) and has identical values
     /// for all its fields.
     /// </summary>
-    bool Equals(object other);
+    new bool Equals(object other);
 
     /// <summary>
     /// Returns the hash code value for this message.
     /// TODO(jonskeet): Specify the hash algorithm, but better than the Java one!
     /// </summary>
-    int GetHashCode();
+    new int GetHashCode();
     #endregion
 
     #region Convenience methods
@@ -163,19 +163,19 @@
     /// Converts the message to a string in protocol buffer text format.
     /// This is just a trivial wrapper around TextFormat.PrintToString.
     /// </summary>
-    string ToString();
+    new string ToString();
 
     /// <summary>
     /// Serializes the message to a ByteString. This is a trivial wrapper
     /// around WriteTo(CodedOutputStream).
     /// </summary>
-    ByteString ToByteString();
+    new ByteString ToByteString();
 
     /// <summary>
     /// Serializes the message to a byte array. This is a trivial wrapper
     /// around WriteTo(CodedOutputStream).
     /// </summary>
-    byte[] ToByteArray();
+    new byte[] ToByteArray();
 
     /// <summary>
     /// Serializes the message and writes it to the given stream.
@@ -183,7 +183,7 @@
     /// does not flush or close the stream.
     /// </summary>
     /// <param name="output"></param>
-    void WriteTo(Stream output);
+    new void WriteTo(Stream output);
     #endregion
 
     /// <summary>
@@ -191,19 +191,19 @@
     /// is typically implemented by strongly typed messages by just returning
     /// the result of CreateBuilderForType.
     /// </summary>
-    IBuilder WeakCreateBuilderForType();
+    new IBuilder WeakCreateBuilderForType();
 
     /// <summary>
     /// Creates a builder with the same contents as this message. This
     /// is typically implemented by strongly typed messages by just returning
     /// the result of ToBuilder.
     /// </summary>
-    IBuilder WeakToBuilder();
+    new IBuilder WeakToBuilder();
 
-    IMessage WeakDefaultInstanceForType { get; }
+    new IMessage WeakDefaultInstanceForType { get; }
   }
 
-  public interface IMessage<TMessage> : IMessage {
+  public interface IMessage<TMessage> : IMessage, IMessageLite<TMessage> {
     /// <summary>
     /// Returns an instance of this message type with all fields set to
     /// their default values. This may or may not be a singleton. This differs
@@ -211,26 +211,26 @@
     /// method is an abstract method of IMessage whereas DefaultInstance is
     /// a static property of a specific class. They return the same thing.
     /// </summary>
-    TMessage DefaultInstanceForType { get; }
+    new TMessage DefaultInstanceForType { get; }
   }
 
   /// <summary>
   /// Type-safe interface for all generated messages to implement.
   /// </summary>
-  public interface IMessage<TMessage, TBuilder> : IMessage<TMessage>
+  public interface IMessage<TMessage, TBuilder> : IMessage<TMessage>, IMessageLite<TMessage, TBuilder>
       where TMessage : IMessage<TMessage, TBuilder> 
       where TBuilder : IBuilder<TMessage, TBuilder> {
     #region Builders
     /// <summary>
     /// Constructs a new builder for a message of the same type as this message.
     /// </summary>
-    TBuilder CreateBuilderForType();
+    new TBuilder CreateBuilderForType();
     /// <summary>
     /// Creates a builder with the same contents as this current instance.
     /// This is typically implemented by strongly typed messages by just
     /// returning the result of ToBuilder().
     /// </summary>
-    TBuilder ToBuilder();
+    new TBuilder ToBuilder();
     #endregion
   }
 }
diff --git a/src/ProtocolBuffers/IMessageLite.cs b/src/ProtocolBuffers/IMessageLite.cs
index ec955c6..cb64e02 100644
--- a/src/ProtocolBuffers/IMessageLite.cs
+++ b/src/ProtocolBuffers/IMessageLite.cs
@@ -35,7 +35,6 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
-using Google.ProtocolBuffers.Descriptors;
 
 namespace Google.ProtocolBuffers {
 
@@ -43,68 +42,7 @@
   /// Non-generic interface used for all parts of the API which don't require
   /// any type knowledge.
   /// </summary>
-  public interface IMessage {
-    /// <summary>
-    /// Returns the message's type's descriptor. This differs from the
-    /// Descriptor property of each generated message class in that this
-    /// method is an abstract method of IMessage whereas Descriptor is
-    /// a static property of a specific class. They return the same thing.
-    /// </summary>
-    MessageDescriptor DescriptorForType { get; }
-    /// <summary>
-    /// Returns a collection of all the fields in this message which are set
-    /// and their corresponding values.  A singular ("required" or "optional")
-    /// field is set iff HasField() returns true for that field.  A "repeated"
-    /// field is set iff GetRepeatedFieldSize() is greater than zero.  The
-    /// values are exactly what would be returned by calling
-    /// GetField(FieldDescriptor) for each field.  The map
-    /// is guaranteed to be a sorted map, so iterating over it will return fields
-    /// in order by field number. 
-    /// </summary>
-    IDictionary<FieldDescriptor, object> AllFields { get; }
-
-    /// <summary>
-    /// Returns true if the given field is set. This is exactly equivalent
-    /// to calling the generated "Has" property corresponding to the field.
-    /// </summary>
-    /// <exception cref="ArgumentException">the field is a repeated field,
-    /// or it's not a field of this type</exception>
-    bool HasField(FieldDescriptor field);
-
-    /// <summary>
-    /// Obtains the value of the given field, or the default value if
-    /// it isn't set. For value type fields, the boxed value is returned.
-    /// For enum fields, the EnumValueDescriptor for the enum is returned.
-    /// For embedded message fields, the sub-message
-    /// is returned. For repeated fields, an IList&lt;T&gt; is returned.
-    /// </summary>
-    object this[FieldDescriptor field] { get; }
-
-    /// <summary>
-    /// Returns the number of elements of a repeated field. This is
-    /// exactly equivalent to calling the generated "Count" property
-    /// corresponding to the field.
-    /// </summary>
-    /// <exception cref="ArgumentException">the field is not a repeated field,
-    /// or it's not a field of this type</exception>
-    int GetRepeatedFieldCount(FieldDescriptor field);
-
-    /// <summary>
-    /// Gets an element of a repeated field. For value type fields 
-    /// excluding enums, the boxed value is returned. For embedded
-    /// message fields, the sub-message is returned. For enums, the
-    /// relevant EnumValueDescriptor is returned.
-    /// </summary>
-    /// <exception cref="ArgumentException">the field is not a repeated field,
-    /// or it's not a field of this type</exception>
-    /// <exception cref="ArgumentOutOfRangeException">the index is out of
-    /// range for the repeated field's value</exception>
-    object this[FieldDescriptor field, int index] { get; }
-
-    /// <summary>
-    /// Returns the unknown fields for this message.
-    /// </summary>
-    UnknownFieldSet UnknownFields { get; }
+  public interface IMessageLite {
 
     /// <summary>
     /// Returns true iff all required fields in the message and all embedded
@@ -191,19 +129,19 @@
     /// is typically implemented by strongly typed messages by just returning
     /// the result of CreateBuilderForType.
     /// </summary>
-    IBuilder WeakCreateBuilderForType();
+    IBuilderLite WeakCreateBuilderForType();
 
     /// <summary>
     /// Creates a builder with the same contents as this message. This
     /// is typically implemented by strongly typed messages by just returning
     /// the result of ToBuilder.
     /// </summary>
-    IBuilder WeakToBuilder();
+    IBuilderLite WeakToBuilder();
 
-    IMessage WeakDefaultInstanceForType { get; }
+    IMessageLite WeakDefaultInstanceForType { get; }
   }
 
-  public interface IMessage<TMessage> : IMessage {
+  public interface IMessageLite<TMessage> : IMessageLite {
     /// <summary>
     /// Returns an instance of this message type with all fields set to
     /// their default values. This may or may not be a singleton. This differs
@@ -217,9 +155,9 @@
   /// <summary>
   /// Type-safe interface for all generated messages to implement.
   /// </summary>
-  public interface IMessage<TMessage, TBuilder> : IMessage<TMessage>
-      where TMessage : IMessage<TMessage, TBuilder> 
-      where TBuilder : IBuilder<TMessage, TBuilder> {
+  public interface IMessageLite<TMessage, TBuilder> : IMessageLite<TMessage>
+      where TMessage : IMessageLite<TMessage, TBuilder> 
+      where TBuilder : IBuilderLite<TMessage, TBuilder> {
     #region Builders
     /// <summary>
     /// Constructs a new builder for a message of the same type as this message.
diff --git a/src/ProtocolBuffers/ProtocolBuffers.csproj b/src/ProtocolBuffers/ProtocolBuffers.csproj
index 703a823..f4fbfe4 100644
--- a/src/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/src/ProtocolBuffers/ProtocolBuffers.csproj
@@ -84,8 +84,11 @@
     <Compile Include="DynamicMessage.cs" />
     <Compile Include="ExtendableBuilder.cs" />
     <Compile Include="ExtendableMessage.cs" />
-    <Compile Include="ExtensionInfo.cs" />
+    <Compile Include="ExtensionInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="ExtensionRegistry.cs" />
+    <Compile Include="ExtensionRegistryLite.cs" />
     <Compile Include="FieldAccess\ReflectionUtil.cs" />
     <Compile Include="FieldAccess\SingleEnumAccessor.cs" />
     <Compile Include="FieldAccess\SingleMessageAccessor.cs" />
@@ -97,12 +100,17 @@
     <Compile Include="FieldAccess\RepeatedMessageAccessor.cs" />
     <Compile Include="FieldSet.cs" />
     <Compile Include="GeneratedBuilder.cs" />
+    <Compile Include="GeneratedExtensionLite.cs" />
     <Compile Include="GeneratedRepeatExtension.cs" />
     <Compile Include="GeneratedSingleExtension.cs" />
     <Compile Include="GeneratedMessage.cs" />
     <Compile Include="IBuilder.cs" />
     <Compile Include="GeneratedExtensionBase.cs" />
+    <Compile Include="IBuilderLite.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="IMessage.cs" />
+    <Compile Include="IMessageLite.cs" />
     <Compile Include="InvalidProtocolBufferException.cs" />
     <Compile Include="IRpcChannel.cs" />
     <Compile Include="IRpcController.cs" />
diff --git a/src/ProtocolBuffers/UninitializedMessageException.cs b/src/ProtocolBuffers/UninitializedMessageException.cs
index 2fa5ef1..d98987a 100644
--- a/src/ProtocolBuffers/UninitializedMessageException.cs
+++ b/src/ProtocolBuffers/UninitializedMessageException.cs
@@ -36,8 +36,10 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Text;
+#if !LITE
 using Google.ProtocolBuffers.Collections;
 using Google.ProtocolBuffers.Descriptors;
+#endif
 
 namespace Google.ProtocolBuffers {
   /// <summary>
@@ -47,13 +49,9 @@
 
     private readonly IList<string> missingFields;
 
-    public UninitializedMessageException(IMessage message)
-        : this(FindMissingFields(message)) {
-    }
-
     private UninitializedMessageException(IList<string> missingFields)
         : base(BuildDescription(missingFields)) {
-      this.missingFields = Lists.AsReadOnly(missingFields);
+      this.missingFields = new List<string>(missingFields);
     }
 
     
@@ -92,6 +90,11 @@
       return description.ToString();
     }
 
+#if !LITE
+    public UninitializedMessageException(IMessage message)
+        : this(FindMissingFields(message)) {
+    }
+
     /// <summary>
     /// Returns a list of the full "paths" of missing required
     /// fields in the specified message.
@@ -148,5 +151,6 @@
       result.Append('.');
       return result.ToString();
     }
+#endif
   }
 }
diff --git a/src/ProtocolBuffers/UnknownField.cs b/src/ProtocolBuffers/UnknownField.cs
index fdc0065..ad1b59b 100644
--- a/src/ProtocolBuffers/UnknownField.cs
+++ b/src/ProtocolBuffers/UnknownField.cs
@@ -172,7 +172,9 @@
         output.WriteBytes(fieldNumber, value);
       }
       foreach (UnknownFieldSet value in groupList) {
+#pragma warning disable 0612
         output.WriteUnknownGroup(fieldNumber, value);
+#pragma warning restore 0612
       }
     }
 
@@ -195,7 +197,9 @@
         result += CodedOutputStream.ComputeBytesSize(fieldNumber, value);
       }
       foreach (UnknownFieldSet value in groupList) {
+#pragma warning disable 0612
         result += CodedOutputStream.ComputeUnknownGroupSize(fieldNumber, value);
+#pragma warning restore 0612
       }
       return result;
     }
diff --git a/src/ProtocolBuffers/UnknownFieldSet.cs b/src/ProtocolBuffers/UnknownFieldSet.cs
index 49c1fa3..e982e31 100644
--- a/src/ProtocolBuffers/UnknownFieldSet.cs
+++ b/src/ProtocolBuffers/UnknownFieldSet.cs
@@ -51,7 +51,7 @@
   /// 
   /// Most users will never need to use this class directly.
   /// </summary>
-  public sealed class UnknownFieldSet {
+  public sealed class UnknownFieldSet : IMessageLite {
 
     private static readonly UnknownFieldSet defaultInstance = new UnknownFieldSet(new Dictionary<int, UnknownField>());
 
@@ -237,16 +237,43 @@
       return CreateBuilder().MergeFrom(input).Build();
     }
 
+    #region IMessageLite Members
+
+    public bool IsInitialized {
+      get { return fields != null; }
+    }
+
+    public void WriteDelimitedTo(Stream output) {
+      CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
+      codedOutput.WriteRawVarint32((uint) SerializedSize);
+      WriteTo(codedOutput);
+      codedOutput.Flush();
+    }
+
+    public IBuilderLite WeakCreateBuilderForType() {
+      return new Builder();
+    }
+
+    public IBuilderLite WeakToBuilder() {
+      return new Builder(fields);
+    }
+
+    public IMessageLite WeakDefaultInstanceForType {
+      get { return defaultInstance; }
+    }
+
+    #endregion
+
     /// <summary>
     /// Builder for UnknownFieldSets.
     /// </summary>
-    public sealed class Builder
+    public sealed class Builder : IBuilderLite
     {
       /// <summary>
       /// Mapping from number to field. Note that by using a SortedList we ensure
       /// that the fields will be serialized in ascending order.
       /// </summary>
-      private IDictionary<int, UnknownField> fields = new SortedList<int, UnknownField>();
+      private IDictionary<int, UnknownField> fields;
       // Optimization:  We keep around a builder for the last field that was
       // modified so that we can efficiently add to it multiple times in a
       // row (important when parsing an unknown repeated field).
@@ -254,6 +281,11 @@
       private UnknownField.Builder lastField;
 
       internal Builder() {
+        fields = new SortedList<int, UnknownField>();
+      }
+
+      internal Builder(IDictionary<int, UnknownField> dictionary) {
+        fields = new SortedList<int, UnknownField>(dictionary); 
       }
 
       /// <summary>
@@ -356,7 +388,9 @@
             return true;
           case WireFormat.WireType.StartGroup: {
             Builder subBuilder = CreateBuilder();
+#pragma warning disable 0612
             input.ReadUnknownGroup(number, subBuilder);
+#pragma warning restore 0612
             GetFieldBuilder(number).AddGroup(subBuilder.Build());
             return true;
           }
@@ -463,12 +497,14 @@
         return this;
       }
 
-      internal void MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder) {
+      internal void MergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistryLite, IBuilder builder) {
         while (true) {
           uint tag = input.ReadTag();
           if (tag == 0) {
             break;
           }
+
+          ExtensionRegistry extensionRegistry = (extensionRegistryLite as ExtensionRegistry) ?? ExtensionRegistry.CreateInstance();
           if (!MergeFieldFrom(input, extensionRegistry, builder, tag)) {
             // end group tag
             break;
@@ -485,7 +521,7 @@
       /// <param name="builder">Builder to merge field into, if it's a known field</param>
       /// <param name="tag">The tag, which should already have been read from the input</param>
       /// <returns>true unless the tag is an end-group tag</returns>
-      internal bool MergeFieldFrom(CodedInputStream input, 
+      internal bool MergeFieldFrom(CodedInputStream input,
           ExtensionRegistry extensionRegistry, IBuilder builder, uint tag) {
 
         MessageDescriptor type = builder.DescriptorForType;
@@ -672,6 +708,54 @@
           builder[field] = subBuilder.WeakBuild();
         }
       }
+
+      #region IBuilderLite Members
+
+      bool IBuilderLite.IsInitialized {
+        get { return fields != null; }
+      }
+
+      IBuilderLite IBuilderLite.WeakClear() {
+        return Clear();
+      }
+
+      IBuilderLite IBuilderLite.WeakMergeFrom(IMessageLite message) {
+        return MergeFrom((UnknownFieldSet)message);
+      }
+
+      IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data) {
+        return MergeFrom(data);
+      }
+
+      IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistryLite registry) {
+        return MergeFrom(data);
+      }
+
+      IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input) {
+        return MergeFrom(input);
+      }
+
+      IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input, ExtensionRegistryLite registry) {
+        return MergeFrom(input);
+      }
+
+      IMessageLite IBuilderLite.WeakBuild() {
+        return Build();
+      }
+
+      IMessageLite IBuilderLite.WeakBuildPartial() {
+        return Build();
+      }
+
+      IBuilderLite IBuilderLite.WeakClone() {
+        return Build().WeakToBuilder();
+      }
+
+      IMessageLite IBuilderLite.WeakDefaultInstanceForType {
+        get { return DefaultInstance; }
+      }
+
+      #endregion
     }
   }
 }
diff --git a/src/ProtocolBuffers/WireFormat.cs b/src/ProtocolBuffers/WireFormat.cs
index 2234646..508f1b4 100644
--- a/src/ProtocolBuffers/WireFormat.cs
+++ b/src/ProtocolBuffers/WireFormat.cs
@@ -33,7 +33,9 @@
 #endregion
 
 using System;
+#if !LITE
 using Google.ProtocolBuffers.Descriptors;
+#endif
 
 namespace Google.ProtocolBuffers {
   
@@ -115,6 +117,7 @@
       return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
     }
 
+#if !LITE
     [CLSCompliant(false)]
     public static uint MakeTag(FieldDescriptor field) {
       return MakeTag(field.FieldNumber, GetWireType(field));
@@ -170,5 +173,6 @@
           throw new ArgumentOutOfRangeException("No such field type");
       }
     }
+#endif
   }
 }