codegenerator.cs

来自「SharpDevelop2.0.0 c#开发免费工具」· CS 代码 · 共 688 行 · 第 1/2 页

CS
688
字号
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
//     <version>$Revision$</version>
// </file>

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

using Microsoft.CSharp;

namespace WrapperGenerator
{
	public class CodeGenerator
	{
		Assembly assembly;
		protected string wrapperNamespace;
		
		string comparsionCode = 
@"		~TheType()" + "\r\n" +
@"		{" + "\r\n" +
@"			object o = wrappedObject;" + "\r\n" +
@"			wrappedObject = null;" + "\r\n" +
@"			ResourceManager.ReleaseCOMObject(o, typeof(TheType));" + "\r\n" +
@"		}" + "\r\n" +
@"		" + "\r\n" +
@"		public bool Is<T>() where T: class" + "\r\n" +
@"		{" + "\r\n" +
@"			try {" + "\r\n" +
@"				CastTo<T>();" + "\r\n" +
@"				return true;" + "\r\n" +
@"			} catch {" + "\r\n" +
@"				return false;" + "\r\n" +
@"			}" + "\r\n" +
@"		}" + "\r\n" +
@"		" + "\r\n" +
@"		public T As<T>() where T: class" + "\r\n" +
@"		{" + "\r\n" +
@"			try {" + "\r\n" +
@"				return CastTo<T>();" + "\r\n" +
@"			} catch {" + "\r\n" +
@"				return null;" + "\r\n" +
@"			}" + "\r\n" +
@"		}" + "\r\n" +
@"		" + "\r\n" +
@"		public T CastTo<T>() where T: class" + "\r\n" +
@"		{" + "\r\n" +
@"			return (T)Activator.CreateInstance(typeof(T), this.WrappedObject);" + "\r\n" +
@"		}" + "\r\n" +
@"		" + "\r\n" +
@"		public static bool operator ==(TheType o1, TheType o2)" + "\r\n" +
@"		{" + "\r\n" +
@"			return ((object)o1 == null && (object)o2 == null) ||" + "\r\n" +
@"			       ((object)o1 != null && (object)o2 != null && o1.WrappedObject == o2.WrappedObject);" + "\r\n" +
@"		}" + "\r\n" +
@"		" + "\r\n" +
@"		public static bool operator !=(TheType o1, TheType o2)" + "\r\n" +
@"		{" + "\r\n" +
@"			return !(o1 == o2);" + "\r\n" +
@"		}" + "\r\n" +
@"		" + "\r\n" +
@"		public override int GetHashCode()" + "\r\n" +
@"		{" + "\r\n" +
@"			return base.GetHashCode();" + "\r\n" +
@"		}" + "\r\n" +
@"		" + "\r\n" +
@"		public override bool Equals(object o)" + "\r\n" +
@"		{" + "\r\n" +
@"			TheType casted = o as TheType;" + "\r\n" +
@"			return (casted != null) && (casted.WrappedObject == wrappedObject);" + "\r\n" +
@"		}" + "\r\n" +
@"		";
		
		public CodeGenerator(Assembly assembly)
		{
			this.assembly = assembly;
		}
		
		protected virtual bool ShouldIncludeType(Type type)
		{
			return true;
		}
		
		protected virtual Type GetBaseClass(Type type) 
		{
			return null;
		}
		
		public IEnumerable<CodeCompileUnit> MakeCompileUnits()
		{
			foreach(Type type in assembly.GetTypes()) {
				if (!ShouldIncludeType(type)) continue;
				
				CodeCompileUnit codeCompileUnit;
				codeCompileUnit = new CodeCompileUnit();
				codeCompileUnit.UserData.Add("filename", type.Name);
				codeCompileUnit.Namespaces.Add(MakeNamespace(type));
				
				yield return codeCompileUnit;
			}
		}
		
		CodeNamespace MakeNamespace(Type type)
		{
			CodeNamespace codeNamespace = new CodeNamespace(wrapperNamespace);
			codeNamespace.Imports.Add(new CodeNamespaceImport("System"));
			codeNamespace.Types.Add(MakeTypeDeclaration(type));
			
			return codeNamespace;
		}
		
		CodeTypeDeclaration MakeTypeDeclaration(Type type)
		{
			if (type.IsEnum) {
				return MakeEnumDeclaration(type);
			} else {
				return MakeClassDeclaration(type);
			}
		}
		
		CodeTypeDeclaration MakeEnumDeclaration(Type type)
		{
			CodeTypeDeclaration enumDeclaration = new CodeTypeDeclaration();
			enumDeclaration.Attributes = MemberAttributes.Private;
			enumDeclaration.Name = type.Name;
			enumDeclaration.IsEnum = true;
			enumDeclaration.BaseTypes.Add(Enum.GetUnderlyingType(type));
			
			if (type.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0) {
				enumDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("Flags"));
			}
			
			foreach(string name in Enum.GetNames(type)) {
				CodeMemberField field = new CodeMemberField();
				field.Name = name;
				object val = Convert.ChangeType(Enum.Parse(type, name), Enum.GetUnderlyingType(type));
				field.InitExpression = new CodePrimitiveExpression(val);
				enumDeclaration.Members.Add(field);
			}
			
			return enumDeclaration;
		}
		
		CodeTypeDeclaration MakeClassDeclaration(Type type)
		{
			Type baseType = GetBaseClass(type);
			
			CodeTypeDeclaration codeTypeDeclaration = new CodeTypeDeclaration();
			codeTypeDeclaration.Attributes = MemberAttributes.Private;
			codeTypeDeclaration.IsPartial = true;
			codeTypeDeclaration.Name = type.Name;
			if (baseType != null) {
				codeTypeDeclaration.BaseTypes.Add(baseType.Name);
			}
			
			codeTypeDeclaration.Members.Add(MakeWrappedObjectField(type));
			codeTypeDeclaration.Members.Add(MakeWrappedObjectProperty(type));
			codeTypeDeclaration.Members.Add(MakeConstructor(type));
			//codeTypeDeclaration.Members.Add(MakeCanWrapMethod(type));
			codeTypeDeclaration.Members.Add(MakeWrapMethod(type));
			codeTypeDeclaration.Members.Add(new CodeSnippetTypeMember(comparsionCode.Replace("TheType", type.Name)));
			codeTypeDeclaration.Members.AddRange(MakeMembers(type));
			
			return codeTypeDeclaration;
		}
		
		CodeMemberField MakeWrappedObjectField(Type type)
		{
			CodeMemberField codeWrappedObjectField = new CodeMemberField();
			codeWrappedObjectField.Attributes = MemberAttributes.Private;
			codeWrappedObjectField.Type = new CodeTypeReference(type.FullName);
			codeWrappedObjectField.Name = "wrappedObject";
			
			return codeWrappedObjectField;
		}
		
		CodeExpression ExpressionForWrappedObjectField {
			get {
				return new CodeFieldReferenceExpression(
							new CodeThisReferenceExpression(),
							"wrappedObject");
			}
		}
		
		CodeMemberProperty MakeWrappedObjectProperty(Type type)
		{
			CodeMemberProperty codeWrappedObjectProperty = new CodeMemberProperty();
			codeWrappedObjectProperty.Attributes = MemberAttributes.Assembly | MemberAttributes.Final;
			codeWrappedObjectProperty.Type = new CodeTypeReference(type.FullName);
			codeWrappedObjectProperty.Name = "WrappedObject";
			codeWrappedObjectProperty.HasGet = true;
			codeWrappedObjectProperty.HasSet = false;
			
			CodeMethodReturnStatement codeGetter = new CodeMethodReturnStatement(ExpressionForWrappedObjectField);
			codeWrappedObjectProperty.GetStatements.Add(codeGetter);
			
			return codeWrappedObjectProperty;
		}
		
		CodeExpression ExpressionForWrappedObjectProperty {
			get {
				return new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "WrappedObject");
			}
		}
		
		CodeConstructor MakeConstructor(Type type)
		{
			Type baseType = GetBaseClass(type);
			
			CodeConstructor codeConstructor = new CodeConstructor();
			codeConstructor.Attributes = MemberAttributes.Public;
			codeConstructor.Parameters.Add(new CodeParameterDeclarationExpression(type, "wrappedObject"));
			
			if (baseType != null) {
				codeConstructor.BaseConstructorArgs.Add(
					new CodeCastExpression(
						GetBaseClass(type).FullName,
						new CodeArgumentReferenceExpression("wrappedObject")));
			}
			
			codeConstructor.Statements.Add(
				new CodeAssignStatement(
					ExpressionForWrappedObjectField,
					new CodeArgumentReferenceExpression("wrappedObject")));
			
			codeConstructor.Statements.Add(
				new CodeMethodInvokeExpression(
					new CodeMethodReferenceExpression(
						new CodeTypeReferenceExpression("ResourceManager"),
						"TrackCOMObject"),
					new CodeArgumentReferenceExpression("wrappedObject"),
					new CodeTypeOfExpression(type.Name)));
			
			return codeConstructor;
		}
		
		/*
		CodeMemberMethod MakeCanWrapMethod(Type wrappedType)
		{
			CodeMemberMethod method = new CodeMemberMethod();
			method.Attributes = MemberAttributes.Static | MemberAttributes.Public;
			method.ReturnType = new CodeTypeReference(typeof(bool));
			method.Name = "CanWrap";
			method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "objectToWrap"));
			
			method.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression("objectToWrap is " + wrappedType.FullName)));
			
			return method;
		}
		*/
		
		CodeMemberMethod MakeWrapMethod(Type wrappedType)
		{
			CodeMemberMethod method = new CodeMemberMethod();
			method.Attributes = MemberAttributes.Static | MemberAttributes.Public;
			method.ReturnType = new CodeTypeReference(wrappedType.Name);
			method.Name = "Wrap";
			method.Parameters.Add(new CodeParameterDeclarationExpression(wrappedType, "objectToWrap"));
			
			/*
			foreach(Type type in wrappedType.Assembly.GetTypes()) {
				if (ShouldIncludeType(type) && GetBaseClass(type).Name == wrappedType.Name) {
					method.Statements.Add(
						new CodeConditionStatement(
							new CodeMethodInvokeExpression(
								new CodeMethodReferenceExpression(
									new CodeTypeReferenceExpression(type.Name),
									"CanWrap"),
								new CodeArgumentReferenceExpression("objectToWrap")),
							new CodeMethodReturnStatement(
								new CodeMethodInvokeExpression(
									new CodeMethodReferenceExpression(
										new CodeTypeReferenceExpression(type.Name),
										"Wrap"),
									new CodeCastExpression(
										namespaceToWrap + "." + type.Name,
										new CodeArgumentReferenceExpression("objectToWrap"))))));
					                                                                               
				}
			}
			*/
			
			method.Statements.Add(
				// if
				new CodeConditionStatement(
					// objectToWrap != null
					new CodeBinaryOperatorExpression(
						new CodeArgumentReferenceExpression("objectToWrap"),
						CodeBinaryOperatorType.IdentityInequality,
						new CodePrimitiveExpression(null)),
					// return new TheType(objectToWrap);
					new CodeStatement[] {
						new CodeMethodReturnStatement(
							new CodeObjectCreateExpression(
								wrappedType.Name,
								new CodeArgumentReferenceExpression("objectToWrap")))},
					// else return null;
					new CodeStatement[] {
						new CodeMethodReturnStatement(
							new CodePrimitiveExpression(null))}));
			
			return method;
		}
		
		CodeTypeMember[] MakeMembers(Type type)
		{
			List<CodeTypeMember> codeTypeMembers = new List<CodeTypeMember>();
			
			foreach(MethodInfo method in type.GetMethods()) {
				if (method.DeclaringType == type) {
					codeTypeMembers.Add(MakeMember(method));
				}
			}
			
			return codeTypeMembers.ToArray();
		}
		
		CodeExpression Unwrap(Type rawType, CodeExpression codeExpression)
		{
			if (rawType.IsEnum) {
				return new CodeCastExpression(
					new CodeTypeReference(rawType),
					codeExpression);
			} else {
				return new CodePropertyReferenceExpression(codeExpression, "WrappedObject");
			}
		}
		
		CodeExpression Wrap(Type rawType, CodeExpression codeExpression)
		{
			if (rawType.IsEnum) {
				return new CodeCastExpression(
					new CodeTypeReference(rawType.Name),
					codeExpression);
			} else {
				return new CodeMethodInvokeExpression(
				           new CodeMethodReferenceExpression(
				               new CodeTypeReferenceExpression(rawType.Name),
				               "Wrap"),

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?