Click here to Skip to main content
15,892,072 members
Articles / Programming Languages / C#

Generate Proxy Class at Build Time

Rate me:
Please Sign up or sign in to vote.
4.74/5 (13 votes)
15 Nov 2011Ms-PL5 min read 36.8K   214   25  
An introduction to Genuilder Extensibility
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Genuilder.Extensibility;
using Genuilder;
using Genuilder.Extensibility.NRefactory;
using ICSharpCode.NRefactory.Visitors;

namespace Membership.Genuilder
{
	public class ProxyGeneratorExtension : IExtension
	{
		class ProxiedInterfaceVisitor : AbstractAstVisitor
		{
			private CodeWriter writer;

			public ProxiedInterfaceVisitor(CodeWriter writer)
			{
				this.writer = writer;
			}

			public override object VisitUsing(ICSharpCode.NRefactory.Ast.Using @using, object data)
			{
				writer.WriteUsing(@using.Name);
				return base.VisitUsing(@using, data);
			}

			public override object VisitNamespaceDeclaration(ICSharpCode.NRefactory.Ast.NamespaceDeclaration namespaceDeclaration, object data)
			{
				using(writer.WriteNamespace(namespaceDeclaration.Name))
				{
					return base.VisitNamespaceDeclaration(namespaceDeclaration, data);
				}
			}

			public override object VisitTypeDeclaration(ICSharpCode.NRefactory.Ast.TypeDeclaration typeDeclaration, object data)
			{
				if(typeDeclaration.Type == ICSharpCode.NRefactory.Ast.ClassType.Interface)
				{
					var typeName = "Proxy" + typeDeclaration.Name;
					writer.Write("public class " + typeName + " : " + typeDeclaration.Name);
					writer.NewLine();
					using(writer.WriteBrackets())
					{
						writer.Write("public " + typeDeclaration.Name + " RealObject { get; private set; }");
						writer.NewLine();
						writer.Write("public " + typeName + "(" + typeDeclaration.Name + " realObject)");
						writer.NewLine();
						using(writer.WriteBrackets())
						{
							writer.Write("this.RealObject = realObject;");
						}
						return base.VisitTypeDeclaration(typeDeclaration, data);
					}

				}
				return null;
			}

			public override object VisitMethodDeclaration(ICSharpCode.NRefactory.Ast.MethodDeclaration methodDeclaration, object data)
			{
				writer.Write("public virtual " + ToName(methodDeclaration.TypeReference) + " " + methodDeclaration.Name + "(" + String.Join(", ", methodDeclaration.Parameters.Select(p => p.TypeReference + " " + p.ParameterName)) + ")");
				writer.NewLine();
				using(writer.WriteBrackets())
				{
					bool isVoid = methodDeclaration.TypeReference.Type == "System.Void";
					writer.Write((isVoid ? "" : "return ") + "RealObject." + methodDeclaration.Name + "(" + String.Join(",", methodDeclaration.Parameters.Select(p => p.ParameterName).ToArray()) + ");");
				}
				return null;
			}

			public override object VisitPropertyDeclaration(ICSharpCode.NRefactory.Ast.PropertyDeclaration propertyDeclaration, object data)
			{
				writer.Write("public virtual " + propertyDeclaration.TypeReference + " " + propertyDeclaration.Name);
				writer.NewLine();
				using(writer.WriteBrackets())
				{
					if(propertyDeclaration.HasGetRegion)
					{
						writer.Write("get");
						writer.NewLine();
						using(writer.WriteBrackets())
						{
							writer.Write("return RealObject." + propertyDeclaration.Name + ";");
						}
					}
					if(propertyDeclaration.HasSetRegion)
					{
						writer.Write("set");
						writer.NewLine();
						using(writer.WriteBrackets())
						{
							writer.Write("RealObject." + propertyDeclaration.Name + " = value;");
						}
					}
				}
				return null;
			}

			private string ToName(ICSharpCode.NRefactory.Ast.TypeReference typeReference)
			{
				if(typeReference.Type == "System.Void")
					return "void";
				return typeReference.ToString();
			}
		}
		#region IExtension Members

		public void Execute(ExtensionContext extensionContext)
		{
			var item = extensionContext.GenItems.FirstOrDefault(o => o.Name == "IRoleProvider.cs");
			item.Logger.Error("See you soon :)", 1, 5);
			if(item != null && item.Modified)
			{
				var asyncItem = item.CreateChildItem("Proxy" + item.Name);
				CodeWriter writer = new CodeWriter(asyncItem.Open());
				var itemAst = item.GetExtension<CompilationUnitExtension>();
				itemAst.ParseMethodBodies = false;
				itemAst.CompilationUnit.AcceptVisitor(new ProxiedInterfaceVisitor(writer), null);
				writer.Flush();
			}
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Software Developer Freelance
France France
I am currently the CTO of Metaco, we are leveraging the Bitcoin Blockchain for delivering financial services.

I also developed a tool to make IaaS on Azure more easy to use IaaS Management Studio.

If you want to contact me, go this way Smile | :)

Comments and Discussions