public void TestWriteDefinition_CustomInstantiateWorks() {
			var tpl = mocks.StrictMock<ITemplate>();
			mocks.ReplayAll();
			string expected = "private Namespace.TestType TestId {" + Environment.NewLine
			                + "	get { return (Namespace.TestType)controls[\"TestId\"]; }" + Environment.NewLine
			                + "	set {" + Environment.NewLine
			                + "		controls[\"TestId\"] = value;" + Environment.NewLine
			                + "		if (!string.IsNullOrEmpty(id))" + Environment.NewLine
			                + "			((IControl)controls[\"TestId\"]).Id = id + \"_TestId\";" + Environment.NewLine
			                + "	}" + Environment.NewLine
			                + "}" + Environment.NewLine + Environment.NewLine;

			var member = new InstantiatedControlMember("TestId", "Namespace.TestType", true, new Dictionary<string, TypedMarkupData>(), new IMember[0]);

			CodeBuilder cb = new CodeBuilder();
			member.WriteCode(tpl, MemberCodePoint.ServerDefinition, cb);
			Assert.AreEqual(expected, cb.ToString());
			Assert.AreEqual(0, cb.IndentLevel);

			cb = new CodeBuilder();
			member.WriteCode(tpl, MemberCodePoint.ClientDefinition, cb);
			Assert.AreEqual(expected, cb.ToString());
			Assert.AreEqual(0, cb.IndentLevel);
			mocks.VerifyAll();
		}
		public void TestWriteIdChangedCode_NothingWritten() {
			var tpl = mocks.StrictMock<ITemplate>();
			mocks.ReplayAll();
			var member = new InstantiatedControlMember("TestId", "Namespace.TestType", false, new Dictionary<string, TypedMarkupData>(), new IMember[0]);

			CodeBuilder cb = new CodeBuilder();
			member.WriteCode(tpl, MemberCodePoint.ServerIdChanging, cb);
			Assert.AreEqual("", cb.ToString());
			Assert.AreEqual(0, cb.IndentLevel);

			cb = new CodeBuilder();
			member.WriteCode(tpl, MemberCodePoint.ClientIdChanging, cb);
			Assert.AreEqual("", cb.ToString());
			Assert.AreEqual(0, cb.IndentLevel);
			mocks.VerifyAll();
		}
		private void TestWriteConstructorCode_NonCustomInstantiateWorks(bool server) {
			var tpl = mocks.StrictMock<ITemplate>();
			mocks.ReplayAll();
			var cb = new CodeBuilder();

			string expected = "{" + Environment.NewLine
			                + "Namespace.Type c = (Namespace.Type)Container.CreateObject(typeof(Namespace.Type));" + Environment.NewLine
			                + "c.Prop1 = value1;" + Environment.NewLine
			                + "c.Prop2 = value2;" + Environment.NewLine
			                + "this.controls[\"CtlName\"] = c;" + Environment.NewLine
			                + "}" + Environment.NewLine;

			var member = new InstantiatedControlMember("CtlName", "Namespace.Type", false, new Dictionary<string, TypedMarkupData>() { { "Prop1", new TypedMarkupData("value1") }, { "Prop2", new TypedMarkupData("value2") } }, new IMember[0]);
			if (server)
				member.WriteCode(tpl, MemberCodePoint.ServerConstructor, cb);
			else
				member.WriteCode(tpl, MemberCodePoint.ClientConstructor, cb);
			Assert.AreEqual(expected, cb.ToString());
			Assert.AreEqual(0, cb.IndentLevel);
			mocks.VerifyAll();
		}
		public bool TryProcess(IDocumentProcessor docProcessor, XmlNode node, bool isRoot, ITemplate template, IRenderFunction currentRenderFunction) {
			if (node.NodeType != XmlNodeType.Element || node.Name != "control")
				return false;
			
			if (isRoot)
				throw ParserUtils.TemplateErrorException("The root element can not be a control.");

			string id = null;
			string type = null;
			bool customInstantiate = false;
			Dictionary<string, TypedMarkupData> additionalProperties = new Dictionary<string, TypedMarkupData>();

			Utils.DoForEachAttribute(node, delegate(XmlAttribute attr) {
				if (attr.Name == "id") {
					if (!ParserUtils.IsValidUnqualifiedName(attr.Value))
						throw ParserUtils.TemplateErrorException("The id '" + attr.Value + "' is not a valid identifier.");
					id = attr.Value;
				}
				else if (attr.Name == "type") {
					if (string.IsNullOrEmpty(attr.Value))
						throw ParserUtils.TemplateErrorException("The control type '" + attr.Value + "' is invalid.");
					type = attr.Value;
				}
				else if (attr.Name == "customInstantiate") {
					string v = attr.Value.ToLowerCase();
					customInstantiate = Utils.ParseBool(v);
				}
				else {
					additionalProperties[attr.Name] = docProcessor.ParseTypedMarkup(attr.Value);
				}
			});
			
			if (customInstantiate && additionalProperties.Count > 0)
				throw ParserUtils.TemplateErrorException("There can not be any property assignments when customInstantiate is true.");

			if (type == null)
				throw ParserUtils.TemplateErrorException("The control '" + id + "' does not have a type specified.");
			if (id == null)
				id = template.GetUniqueId();
			if (template.HasMember(id))
				throw ParserUtils.TemplateErrorException("Duplicate definition of member " + id);

			var dependencies = new List<IMember>();
			int numInnerFragments = 0;
			if (Utils.GetNumChildNodes(node) > 0) {
				Utils.DoForEachChild(node, delegate(XmlNode n) {
					if (n.OuterXml.Trim() != "") {
						numInnerFragments++;
						string innerName = id + "_inner" + Utils.ToStringInvariantInt(numInnerFragments);
						if (template.HasMember(innerName))
							throw ParserUtils.TemplateErrorException("The internal name " + innerName + " is already in use.");
						IRenderFunction innerFunction = new RenderFunctionMember(innerName, "");
						template.AddMember((IMember)innerFunction);
						docProcessor.ProcessRecursive(n, template, innerFunction);
						dependencies.Add(innerFunction);
					}
				});
			}
			
			if (!template.HasMember("Container"))
				template.AddMember(new PropertyMember("Container", "IContainer", "IContainer", AccessModifier._Public, "_container", "IContainer", "IContainer", true, true, null, true));

			IMember controlMember = new InstantiatedControlMember(id, type, customInstantiate, additionalProperties, dependencies);
			template.AddMember(controlMember);

			currentRenderFunction.AddFragment(new InstantiatedControlFragment(id, customInstantiate, numInnerFragments));
			currentRenderFunction.AddDependency(controlMember);

			return true;
		}