Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@927 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
12 changed files with 1083 additions and 0 deletions
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
using System.Reflection; |
||||
using System.Runtime.CompilerServices; |
||||
|
||||
// Information about this assembly is defined by the following
|
||||
// attributes.
|
||||
//
|
||||
// change them to the information which is associated with the assembly
|
||||
// you compile.
|
||||
|
||||
[assembly: AssemblyTitle("")] |
||||
[assembly: AssemblyDescription("")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyCompany("")] |
||||
[assembly: AssemblyProduct("")] |
||||
[assembly: AssemblyCopyright("")] |
||||
[assembly: AssemblyTrademark("")] |
||||
[assembly: AssemblyCulture("")] |
||||
|
||||
// The assembly version has following format :
|
||||
//
|
||||
// Major.Minor.Build.Revision
|
||||
//
|
||||
// You can specify all values by your own or you can build default build and revision
|
||||
// numbers with the '*' character (the default):
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")] |
||||
|
@ -0,0 +1,615 @@
@@ -0,0 +1,615 @@
|
||||
// <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 = |
||||
@" 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.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"))); |
||||
|
||||
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( |
||||
new CodeMethodReturnStatement( |
||||
new CodeObjectCreateExpression( |
||||
wrappedType.Name, |
||||
new CodeArgumentReferenceExpression("objectToWrap")))); |
||||
|
||||
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"), |
||||
codeExpression); |
||||
} |
||||
} |
||||
|
||||
class MethodContext |
||||
{ |
||||
CodeMemberMethod codeMemberMethod = new CodeMemberMethod(); |
||||
CodeGenerator generator; |
||||
|
||||
public string Name; |
||||
public bool IsReturnTypeWrapped; |
||||
public Type RawReturnType; |
||||
public string WrappedReturnType; |
||||
|
||||
public List<CodeParameterDeclarationExpression> WrapperParams = new List<CodeParameterDeclarationExpression>(); |
||||
public List<CodeStatement> DoBeforeInvoke = new List<CodeStatement>(); |
||||
public List<CodeExpression> BaseMethodInvokeParams = new List<CodeExpression>(); |
||||
public List<CodeStatement> DoAfterInvoke = new List<CodeStatement>(); |
||||
|
||||
public MethodContext(CodeGenerator generator, MethodInfo method) |
||||
{ |
||||
this.generator = generator; |
||||
Name = method.Name; |
||||
RawReturnType = method.ReturnType; |
||||
IsReturnTypeWrapped = generator.ShouldIncludeType(method.ReturnType); |
||||
if (IsReturnTypeWrapped) { |
||||
WrappedReturnType = method.ReturnType.Name; |
||||
} else { |
||||
WrappedReturnType = method.ReturnType.FullName; |
||||
} |
||||
|
||||
codeMemberMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; |
||||
codeMemberMethod.ReturnType = new CodeTypeReference(WrappedReturnType); |
||||
codeMemberMethod.Name = method.Name; |
||||
} |
||||
|
||||
public CodeMemberMethod Emit() |
||||
{ |
||||
CodeExpression baseInvoke = |
||||
new CodeMethodInvokeExpression( |
||||
new CodeMethodReferenceExpression( |
||||
generator.ExpressionForWrappedObjectProperty, |
||||
Name), |
||||
BaseMethodInvokeParams.ToArray()); |
||||
|
||||
if (IsReturnTypeWrapped) { |
||||
baseInvoke = generator.Wrap(RawReturnType, baseInvoke); |
||||
} |
||||
|
||||
CodeStatement doInvoke; |
||||
|
||||
if (WrappedReturnType != typeof(void).FullName) { |
||||
if (DoAfterInvoke.Count == 0) { |
||||
doInvoke = new CodeMethodReturnStatement(baseInvoke); |
||||
} else { |
||||
DoBeforeInvoke.Insert(0, |
||||
new CodeVariableDeclarationStatement(WrappedReturnType, "returnValue")); |
||||
doInvoke = |
||||
new CodeAssignStatement( |
||||
new CodeVariableReferenceExpression("returnValue"), |
||||
baseInvoke); |
||||
DoAfterInvoke.Add( |
||||
new CodeMethodReturnStatement( |
||||
new CodeVariableReferenceExpression("returnValue"))); |
||||
} |
||||
} else { |
||||
doInvoke = new CodeExpressionStatement(baseInvoke); |
||||
} |
||||
|
||||
codeMemberMethod.Statements.AddRange(DoBeforeInvoke.ToArray()); |
||||
codeMemberMethod.Statements.Add(doInvoke); |
||||
codeMemberMethod.Statements.AddRange(DoAfterInvoke.ToArray()); |
||||
codeMemberMethod.Parameters.AddRange(WrapperParams.ToArray()); |
||||
|
||||
return codeMemberMethod; |
||||
} |
||||
} |
||||
|
||||
class ParamContext |
||||
{ |
||||
public string Name; |
||||
public bool IsWrapped; |
||||
public string WrappedType; |
||||
public Type RawType; |
||||
public CodeTypeReference TypeRef; |
||||
public FieldDirection Direction; |
||||
public CodeParameterDeclarationExpression ArgDeclaration; |
||||
public CodeArgumentReferenceExpression ArgRefExpression; |
||||
public CodeExpression UnwrappedArgExpression; |
||||
public CodeExpression UnwrappedDirectionalArgExpression; |
||||
|
||||
public ParamContext(CodeGenerator generator, ParameterInfo par) |
||||
{ |
||||
Name = par.Name; |
||||
if (par.ParameterType.IsByRef) { |
||||
RawType = par.ParameterType.GetElementType(); |
||||
} else { |
||||
RawType = par.ParameterType; |
||||
} |
||||
|
||||
IsWrapped = generator.ShouldIncludeType(RawType); |
||||
WrappedType = IsWrapped ? RawType.Name : RawType.FullName; |
||||
TypeRef = new CodeTypeReference(WrappedType); |
||||
if (!par.ParameterType.IsByRef) { |
||||
Direction = FieldDirection.In; |
||||
} else if (par.IsOut) { |
||||
Direction = FieldDirection.Out; |
||||
} else { |
||||
Direction = FieldDirection.Ref; |
||||
} |
||||
|
||||
ArgDeclaration = new CodeParameterDeclarationExpression(); |
||||
ArgDeclaration.Type = TypeRef; |
||||
ArgDeclaration.Name = par.Name; |
||||
ArgDeclaration.Direction = Direction; |
||||
|
||||
ArgRefExpression = new CodeArgumentReferenceExpression(par.Name); |
||||
UnwrappedArgExpression = IsWrapped?generator.Unwrap(RawType, ArgRefExpression):ArgRefExpression; |
||||
UnwrappedDirectionalArgExpression = new CodeDirectionExpression(Direction, UnwrappedArgExpression); |
||||
} |
||||
} |
||||
|
||||
CodeMemberMethod MakeMember(MethodInfo method) |
||||
{ |
||||
MethodContext methodContext = new MethodContext(this, method); |
||||
|
||||
foreach(ParameterInfo par in method.GetParameters()) { |
||||
ParamContext parContext = new ParamContext(this, par); |
||||
|
||||
if (parContext.IsWrapped) { |
||||
if (parContext.Direction == FieldDirection.In) { |
||||
if (par.ParameterType.IsArray) { |
||||
UnwrapArrayArgument(methodContext, parContext); |
||||
} else { |
||||
UnwrapArgument(methodContext, parContext); |
||||
} |
||||
} else { |
||||
UnwrapRefArgument(methodContext, parContext); |
||||
} |
||||
} else { |
||||
PassArgument(methodContext, parContext); |
||||
} |
||||
} |
||||
|
||||
return methodContext.Emit(); |
||||
} |
||||
|
||||
void PassArgument(MethodContext methodContext, ParamContext parContext) |
||||
{ |
||||
methodContext.WrapperParams.Add(parContext.ArgDeclaration); |
||||
methodContext.BaseMethodInvokeParams.Add(parContext.UnwrappedDirectionalArgExpression); |
||||
} |
||||
|
||||
void UnwrapArgument(MethodContext methodContext, ParamContext parContext) |
||||
{ |
||||
methodContext.WrapperParams.Add(parContext.ArgDeclaration); |
||||
methodContext.BaseMethodInvokeParams.Add(parContext.UnwrappedDirectionalArgExpression); |
||||
} |
||||
|
||||
void UnwrapRefArgument(MethodContext methodContext, ParamContext parContext) |
||||
{ |
||||
methodContext.WrapperParams.Add(parContext.ArgDeclaration); |
||||
|
||||
CodeVariableDeclarationStatement tmpVariableDeclaration = new CodeVariableDeclarationStatement(parContext.RawType, ((parContext.Direction==FieldDirection.Ref)?"ref":"out") + "_" + parContext.Name); |
||||
if (parContext.Direction == FieldDirection.Ref) { |
||||
tmpVariableDeclaration.InitExpression = parContext.UnwrappedArgExpression; |
||||
} |
||||
CodeExpression tmpVariableExpression = new CodeVariableReferenceExpression(tmpVariableDeclaration.Name); |
||||
CodeExpression tmpVariableDirectionalExpression = new CodeDirectionExpression(parContext.Direction, tmpVariableExpression); |
||||
methodContext.DoBeforeInvoke.Add(tmpVariableDeclaration); |
||||
|
||||
methodContext.BaseMethodInvokeParams.Add(tmpVariableDirectionalExpression); |
||||
|
||||
CodeAssignStatement assignExpression = new CodeAssignStatement(parContext.ArgRefExpression, Wrap(parContext.RawType, tmpVariableExpression)); |
||||
methodContext.DoAfterInvoke.Add(assignExpression); |
||||
} |
||||
|
||||
void UnwrapArrayArgument(MethodContext methodContext, ParamContext parContext) |
||||
{ |
||||
//OUTPUT:
|
||||
//
|
||||
// public void void__array(Test[] arg)
|
||||
// {
|
||||
// Debugger.Interop.CorDebug.Test[] array_arg = new Debugger.Interop.CorDebug.Test[arg.Length];
|
||||
// for (int i = 0; (i < arg.Length); i = (i + 1))
|
||||
// {
|
||||
// if ((arg[i] != null))
|
||||
// {
|
||||
// array_arg[i] = arg[i].WrappedObject;
|
||||
// }
|
||||
// }
|
||||
// this.WrappedObject.void__array(array_arg);
|
||||
// for (int i = 0; (i < arg.Length); i = (i + 1))
|
||||
// {
|
||||
// if ((array_arg[i] != null))
|
||||
// {
|
||||
// arg[i] = Test.Wrap(array_arg[i]);
|
||||
// } else
|
||||
// {
|
||||
// arg[i] = null;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
methodContext.WrapperParams.Add(parContext.ArgDeclaration); |
||||
|
||||
string rawArrayName = "array_" + parContext.Name; |
||||
|
||||
CodeExpression arg_Length = |
||||
// arg.Length
|
||||
new CodePropertyReferenceExpression(parContext.ArgRefExpression, "Length"); |
||||
CodeExpression i = |
||||
// i
|
||||
new CodeVariableReferenceExpression("i"); |
||||
CodeStatement loopInit = |
||||
// int i = 0
|
||||
new CodeVariableDeclarationStatement(typeof(int), "i", new CodePrimitiveExpression(0)); |
||||
CodeExpression loopCondition = |
||||
// (i < arg.Length)
|
||||
new CodeBinaryOperatorExpression( |
||||
i, |
||||
CodeBinaryOperatorType.LessThan, |
||||
arg_Length); |
||||
CodeStatement loopIteration = |
||||
// i = (i + 1)
|
||||
new CodeAssignStatement( |
||||
i, |
||||
new CodeBinaryOperatorExpression( |
||||
i, |
||||
CodeBinaryOperatorType.Add, |
||||
new CodePrimitiveExpression(1))); |
||||
CodeExpression arg_i = |
||||
// arg[i]
|
||||
new CodeIndexerExpression( |
||||
parContext.ArgRefExpression, |
||||
i); |
||||
CodeVariableReferenceExpression array_arg = |
||||
// array_arg
|
||||
new CodeVariableReferenceExpression(rawArrayName); |
||||
CodeExpression array_arg_i = |
||||
// array_arg[i]
|
||||
new CodeIndexerExpression( |
||||
array_arg, |
||||
i); |
||||
|
||||
// Debugger.Interop.CorDebug.Test[] array_arg = new Debugger.Interop.CorDebug.Test[arg.Length];
|
||||
methodContext.DoBeforeInvoke.Add( |
||||
new CodeVariableDeclarationStatement( |
||||
new CodeTypeReference(parContext.RawType), |
||||
array_arg.VariableName, |
||||
new CodeArrayCreateExpression(parContext.RawType, arg_Length))); |
||||
|
||||
methodContext.DoBeforeInvoke.Add( |
||||
new CodeIterationStatement( |
||||
loopInit, |
||||
loopCondition, |
||||
loopIteration, |
||||
// if
|
||||
new CodeConditionStatement( |
||||
// (arg[i] != null)
|
||||
new CodeBinaryOperatorExpression( |
||||
arg_i, |
||||
CodeBinaryOperatorType.IdentityInequality, |
||||
new CodePrimitiveExpression(null)), |
||||
// array_arg[i] = arg[i].WrappedObject;
|
||||
new CodeAssignStatement( |
||||
array_arg_i, |
||||
Unwrap(parContext.RawType, arg_i))))); |
||||
|
||||
methodContext.DoAfterInvoke.Add( |
||||
new CodeIterationStatement( |
||||
loopInit, |
||||
loopCondition, |
||||
loopIteration, |
||||
// if
|
||||
new CodeConditionStatement( |
||||
// (array_arg[i] != null)
|
||||
new CodeBinaryOperatorExpression( |
||||
array_arg_i, |
||||
CodeBinaryOperatorType.IdentityInequality, |
||||
new CodePrimitiveExpression(null)), |
||||
//
|
||||
new CodeStatement [] { |
||||
// arg[i] = Test.Wrap(array_arg[i]);
|
||||
new CodeAssignStatement( |
||||
arg_i, |
||||
Wrap( |
||||
parContext.RawType.Assembly.GetType(parContext.RawType.FullName.Replace("[]","")), |
||||
array_arg_i))}, |
||||
// else
|
||||
new CodeStatement [] { |
||||
// arg[i] = null;
|
||||
new CodeAssignStatement( |
||||
arg_i, |
||||
new CodePrimitiveExpression(null))}))); |
||||
|
||||
methodContext.BaseMethodInvokeParams.Add(array_arg); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
// <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 CorDebugGenerator: CodeGenerator |
||||
{ |
||||
string namespaceToWrap = "Debugger.Interop.CorDebug"; |
||||
|
||||
public CorDebugGenerator(Assembly assembly):base(assembly) |
||||
{ |
||||
wrapperNamespace = "Debugger.Wrappers.CorDebug"; |
||||
} |
||||
|
||||
protected override bool ShouldIncludeType(Type type) |
||||
{ |
||||
return type.Namespace == namespaceToWrap && |
||||
(type.IsClass || type.IsInterface || type.IsEnum); |
||||
} |
||||
|
||||
protected override Type GetBaseClass(Type type) |
||||
{ |
||||
// Type[] interfaces = type.GetInterfaces();
|
||||
// if (interfaces.Length > 0) {
|
||||
// return interfaces[0];
|
||||
// }
|
||||
// if (type.Name.EndsWith("2")) {
|
||||
// return type.Assembly.GetType(type.FullName.Remove(type.FullName.Length - 1));
|
||||
// }
|
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
// <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 FileGenerator |
||||
{ |
||||
CodeGenerator codeGenerator; |
||||
string header; |
||||
|
||||
public FileGenerator(CodeGenerator codeGenerator, string header) |
||||
{ |
||||
this.codeGenerator = codeGenerator; |
||||
this.header = header; |
||||
} |
||||
|
||||
public string SaveFiles(string saveDirectory) |
||||
{ |
||||
string allCode = ""; |
||||
|
||||
foreach(CodeCompileUnit compileUnit in codeGenerator.MakeCompileUnits()) { |
||||
string code = GenerateCode(compileUnit); |
||||
code = code.Remove(0, code.IndexOf("namespace")); |
||||
|
||||
allCode += code; |
||||
|
||||
string className = (string)compileUnit.UserData["filename"]; |
||||
|
||||
TextWriter textWriter = new StreamWriter(Path.Combine(saveDirectory, className + ".cs")); |
||||
textWriter.Write(header); |
||||
textWriter.Write(code); |
||||
textWriter.Close(); |
||||
} |
||||
|
||||
return allCode; |
||||
} |
||||
|
||||
string GenerateCode(CodeCompileUnit compileUnit) |
||||
{ |
||||
CSharpCodeProvider provider = new CSharpCodeProvider(); |
||||
|
||||
TextWriter stringWriter = new StringWriter(); |
||||
|
||||
CodeGeneratorOptions options = new CodeGeneratorOptions(); |
||||
options.BlankLinesBetweenMembers = true; |
||||
options.BracingStyle = "C"; |
||||
options.ElseOnClosing = true; |
||||
options.IndentString = "\t"; |
||||
options.VerbatimOrder = true; |
||||
|
||||
provider.GenerateCodeFromCompileUnit(compileUnit, stringWriter, options); |
||||
|
||||
return stringWriter.ToString(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
// <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.Collections.Generic; |
||||
using System.CodeDom; |
||||
using System.CodeDom.Compiler; |
||||
using System.Drawing; |
||||
using System.IO; |
||||
using System.Reflection; |
||||
using System.Windows.Forms; |
||||
|
||||
using Microsoft.CSharp; |
||||
|
||||
namespace WrapperGenerator |
||||
{ |
||||
public class MainForm : System.Windows.Forms.Form |
||||
{ |
||||
string header = |
||||
"// <file>" + "\r\n" + |
||||
"// <copyright see=\"prj:///doc/copyright.txt\"/>" + "\r\n" + |
||||
"// <license see=\"prj:///doc/license.txt\"/>" + "\r\n" + |
||||
"// <owner name=\"David Srbecký\" email=\"dsrbecky@gmail.com\"/>" + "\r\n" + |
||||
"// <version>$Revision$</version>" + "\r\n" + |
||||
"// </file>" + "\r\n" + |
||||
"\r\n"; |
||||
//string dllFileName = Assembly.GetExecutingAssembly().Location;
|
||||
string dllFileName = Path.Combine(Assembly.GetExecutingAssembly().Location, @"..\..\..\..\..\..\AddIns\AddIns\Misc\Debugger\Debugger.Core.dll"); |
||||
string saveDirectory = Path.Combine(Assembly.GetExecutingAssembly().Location, @"..\..\..\..\..\..\src\AddIns\Misc\Debugger\Debugger.Core\Project\Src\Wrappers\CorDebug"); |
||||
|
||||
public MainForm() |
||||
{ |
||||
InitializeComponent(); |
||||
|
||||
CodeGenerator codeGenerator = new CorDebugGenerator(Assembly.LoadFile(dllFileName)); |
||||
textBox1.Text = new FileGenerator(codeGenerator, header).SaveFiles(saveDirectory); |
||||
} |
||||
|
||||
[STAThread] |
||||
public static void Main(string[] args) |
||||
{ |
||||
Application.EnableVisualStyles(); |
||||
Application.Run(new MainForm()); |
||||
} |
||||
|
||||
#region Windows Forms Designer generated code
|
||||
/// <summary>
|
||||
/// This method is required for Windows Forms designer support.
|
||||
/// Do not change the method contents inside the source code editor. The Forms designer might
|
||||
/// not be able to load this method if it was changed manually.
|
||||
/// </summary>
|
||||
private void InitializeComponent() |
||||
{ |
||||
textBox1 = new System.Windows.Forms.TextBox(); |
||||
this.SuspendLayout(); |
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 21F); |
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; |
||||
this.ClientSize = new System.Drawing.Size(949, 717); |
||||
//
|
||||
// textBox1
|
||||
//
|
||||
textBox1.Dock = System.Windows.Forms.DockStyle.Fill; |
||||
textBox1.Location = new System.Drawing.Point(0, 0); |
||||
textBox1.Multiline = true; |
||||
textBox1.Name = "textBox1"; |
||||
textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; |
||||
textBox1.Size = new System.Drawing.Size(949, 717); |
||||
textBox1.TabIndex = 0; |
||||
this.Controls.Add(textBox1); |
||||
this.Name = "MainForm"; |
||||
this.Text = "MainForm"; |
||||
this.PerformLayout(); |
||||
this.ResumeLayout(false); |
||||
} |
||||
private System.Windows.Forms.TextBox textBox1; |
||||
#endregion
|
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
// <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; |
||||
|
||||
namespace Debugger.Interop.CorDebug |
||||
{ |
||||
[Flags] |
||||
public enum Enumeration:byte { A = 1, B = 2, C = 4, D = 16 }; |
||||
|
||||
public interface Test { |
||||
// Return values
|
||||
void void__void(); |
||||
|
||||
int int__void(); |
||||
|
||||
string string__void(); |
||||
|
||||
Test Test__void(); |
||||
|
||||
// Direction of parameter - base type
|
||||
void void__inString(string str); |
||||
|
||||
void void__outString(out string str); |
||||
|
||||
void void__refString(ref string str); |
||||
|
||||
// Direction of parameter - wrapped type
|
||||
void void__inTest(Test str); |
||||
|
||||
void void__outTest(out Test t); |
||||
|
||||
void void__refTest(ref Test t); |
||||
|
||||
// Direction of many parameters + return value - base type
|
||||
void void__out_ref_in_out_ref__string(out string p1, ref string p2, string p3, out string p4, ref string p5); |
||||
|
||||
string string__out_ref_in_out_ref__string(out string p1, ref string p2, string p3, out string p4, ref string p5); |
||||
|
||||
// Direction of many parameters + return value - wrapped type
|
||||
void void__out_ref_in_out_ref__Test(out Test p1, ref Test p2, Test p3, out Test p4, ref Test p5); |
||||
|
||||
Test Test__out_ref_in_out_ref__Test(out Test p1, ref Test p2, Test p3, out Test p4, ref Test p5); |
||||
|
||||
// Arrays
|
||||
|
||||
void void__array(Test[] arg); |
||||
} |
||||
} |
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
// <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>
|
||||
|
||||
namespace Debugger.Wrappers.CorDebug |
||||
{ |
||||
using System; |
||||
|
||||
|
||||
public abstract class Wrapper : MarshalByRefObject |
||||
{ |
||||
public abstract object WrappedObject |
||||
{ |
||||
get; |
||||
} |
||||
|
||||
//public staticType WrappedObjectType
|
||||
//{
|
||||
// get;
|
||||
//}
|
||||
} |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<PropertyGroup> |
||||
<OutputType>WinExe</OutputType> |
||||
<RootNamespace>WrapperGenerator</RootNamespace> |
||||
<AssemblyName>WrapperGenerator</AssemblyName> |
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||
<ProjectGuid>{7ED425D8-30CA-422C-90DF-1CB901E46DE3}</ProjectGuid> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> |
||||
<OutputPath>bin\Debug\</OutputPath> |
||||
<Optimize>False</Optimize> |
||||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
<DebugSymbols>True</DebugSymbols> |
||||
<DebugType>Full</DebugType> |
||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> |
||||
<OutputPath>bin\Release\</OutputPath> |
||||
<Optimize>True</Optimize> |
||||
<DefineConstants>TRACE</DefineConstants> |
||||
<DebugSymbols>False</DebugSymbols> |
||||
<DebugType>None</DebugType> |
||||
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<Reference Include="System" /> |
||||
<Reference Include="System.Data" /> |
||||
<Reference Include="System.Drawing" /> |
||||
<Reference Include="System.Windows.Forms" /> |
||||
<Reference Include="System.Xml" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Compile Include="MainForm.cs" /> |
||||
<Compile Include="AssemblyInfo.cs" /> |
||||
<EmbeddedResource Include="MainForm.resources" /> |
||||
<Compile Include="CodeGenerator.cs" /> |
||||
<Compile Include="CorDebugGenerator.cs" /> |
||||
<Compile Include="Test.cs" /> |
||||
<Compile Include="FileGenerator.cs" /> |
||||
</ItemGroup> |
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> |
||||
</Project> |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00 |
||||
# SharpDevelop 2.0.0.920 |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WrapperGenerator", "WrapperGenerator.csproj", "{7ED425D8-30CA-422C-90DF-1CB901E46DE3}" |
||||
EndProject |
||||
Global |
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||
Debug|Any CPU = Debug|Any CPU |
||||
Release|Any CPU = Release|Any CPU |
||||
EndGlobalSection |
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||
{7ED425D8-30CA-422C-90DF-1CB901E46DE3}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{7ED425D8-30CA-422C-90DF-1CB901E46DE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{7ED425D8-30CA-422C-90DF-1CB901E46DE3}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{7ED425D8-30CA-422C-90DF-1CB901E46DE3}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
EndGlobalSection |
||||
EndGlobal |
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
// <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>
|
||||
|
||||
namespace Debugger.Wrappers.CorDebug |
||||
{ |
||||
using System; |
||||
using System.Collections; |
||||
using System.Reflection; |
||||
using System.Runtime.Remoting; |
||||
using System.Runtime.Remoting.Proxies; |
||||
using System.Runtime.Remoting.Messaging; |
||||
|
||||
|
||||
public class WrapperProxy : RealProxy, IRemotingTypeInfo |
||||
{ |
||||
Hashtable wrappingClassCache = new Hashtable(); |
||||
|
||||
MarshalByRefObject wrappedComObject; |
||||
|
||||
public WrapperProxy(MarshalByRefObject objectToWrapp) : |
||||
base (typeof(MarshalByRefObject)) |
||||
{ |
||||
wrappedObject = objectToWrapp; |
||||
} |
||||
|
||||
void GetWrappingClass(Type interfaceType) |
||||
{ |
||||
object cachedItem = wrappingClassCache[interfaceType]; |
||||
if (cachedItem != null) { |
||||
return cachedItem; |
||||
} |
||||
|
||||
interfaceType.GetCustomAttributes(typeof(WrappingClassAttribute), false); |
||||
|
||||
// TODO
|
||||
|
||||
Type wrappingClassType; |
||||
|
||||
object wrappingClass = Activator.CreateInstance(wrappingClassType, wrappedComObject); |
||||
|
||||
wrappingClassCache.Add(interfaceType, wrappingClass); |
||||
} |
||||
|
||||
public override IMessage Invoke(IMessage msg) |
||||
{ |
||||
Type interfaceType = (msg as IMethodCallMessage).MethodBase.ReflectedType; |
||||
|
||||
MarshalByRefObject wrappingClass = GetWrappingClass(wrappingClassType); |
||||
|
||||
return RemotingServices.ExecuteMessage(wrappingClass, msg as IMethodCallMessage); |
||||
} |
||||
|
||||
public string TypeName { |
||||
get { |
||||
return wrappedObject.GetType().FullName; |
||||
} |
||||
set { |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public bool CanCastTo(Type type, object o) |
||||
{ |
||||
Wrapper wrappedObject = o as Wrapper; |
||||
|
||||
if (wrappedObject == null) { |
||||
return false; |
||||
} |
||||
|
||||
if (!type.IsSubclassOf(typeof(Wrapper))) { |
||||
return false; |
||||
} |
||||
|
||||
try { |
||||
Activator.CreateInstance(type, wrappedObject.WrappedObject); |
||||
return true; |
||||
} |
||||
catch { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
// <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>
|
||||
|
||||
namespace Debugger.Wrappers.CorDebug |
||||
{ |
||||
using System; |
||||
|
||||
|
||||
public class WrappingClassAttribute |
||||
{ |
||||
|
||||
} |
||||
} |
Loading…
Reference in new issue