/*
The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language
governing rights and limitations under the License.
The Original Code is RAIL(Runtime Assembly Instrumentation Library) Alpha Version.
The Initial Developer of the Original Code is University of Coimbra,
Computer Science Department, Dependable Systems Group. Copyright (C) University of Coimbra.
All Rights Reserved.
*/
namespace Rail.Reflect{
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;
using System.Globalization;
using System.Collections;
using System.Runtime.InteropServices;
/// <summary>
/// Converts the Rail objects into Reflection.Emit objects
/// </summary>
internal sealed class TypeResolver
{
/// <summary>
///
/// </summary>
internal readonly RAssemblyDef asmRail;
/// <summary>
///
/// </summary>
internal readonly AssemblyBuilder asmREmit;
/// <summary>
///
/// </summary>
private Hashtable TypeBuilders;
/// <summary>
///
/// </summary>
private Hashtable MethodBuilders;
/// <summary>
///
/// </summary>
private Hashtable ConstructorBuilders;
/// <summary>
///
/// </summary>
private Hashtable FieldBuilders;
/// <summary>
///
/// </summary>
private Hashtable PropertyBuilders;
/// <summary>
///
/// </summary>
private Hashtable EventBuilders;
/// <summary>
///
/// </summary>
private Hashtable CustomAttributeBuilders;
/// <summary>
/// Creates a TypeResolver using the context defined by the given <code>RAssembly</code>
/// and <code>AssemblyBuilder</code>.
/// </summary>
/// <param name="asmRail"></param>
/// <param name="asmREmit"></param>
public TypeResolver(RAssemblyDef asmRail, AssemblyBuilder asmREmit)
{
if (asmRail == null)
throw new InvalidProgramException();
if (asmREmit == null)
throw new InvalidProgramException();
this.asmRail = asmRail;
this.asmREmit = asmREmit;
this.TypeBuilders = new Hashtable();
this.MethodBuilders = new Hashtable();
this.ConstructorBuilders = new Hashtable();
this.FieldBuilders = new Hashtable();
this.TypeBuilders = new Hashtable();
this.PropertyBuilders = new Hashtable();
this.EventBuilders = new Hashtable();
this.CustomAttributeBuilders = new Hashtable();
}
/// <summary>
///
/// </summary>
/// <param name="assmDef"></param>
/// <param name="abAccess"></param>
/// <returns></returns>
public static AssemblyBuilder ResolveRAssembly(RAssemblyDef assmDef, AssemblyBuilderAccess abAccess)
{
AssemblyBuilder assmBldr = null;
AssemblyBuilderAccess access = abAccess;
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = assmDef.Name.Name;
assemblyName.Version = new Version(assmDef.Name.Version.Major,assmDef.Name.Version.Minor,assmDef.Name.Version.Build,assmDef.Name.Version.Revision);
//FIX : Hot to get the culture number by the name
//TODO : read the correct culture code from the assembly and create a valid cultureinfo object
assemblyName.CultureInfo = CultureInfo.InvariantCulture;
if (assmDef.Name.PublicKeyToken!=null)
assemblyName.SetPublicKeyToken(assmDef.Name.PublicKeyToken);
else assemblyName.SetPublicKeyToken(null);
assmBldr = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,access,"..\\");
//END OF FIX
return assmBldr;
}
/// <summary>
/// Resolves the RModuleDef into a ModuleBuilder
/// </summary>
/// <param name="module"></param>
/// <returns></returns>
public Module ResolveRModule(RModuleDef module)
{
string moduleFileName = module.FileName;
string moduleName = module.Name;
Module m = this.asmREmit.GetModule(moduleName);
if (m == null)
{
ModuleBuilder moduleBuilder = asmREmit.DefineDynamicModule(moduleName,moduleFileName,true);
m = (Module) moduleBuilder;
}
return m;
}
/// <summary>
/// Resolves the RModuleDef into a ModuleBuilder
/// </summary>
/// <param name="module"></param>
/// <param name="filename"></param>
/// <returns></returns>
public Module ResolveRModule(RModuleDef module, string filename)
{
string moduleFileName = filename;
string moduleName = filename;
module.Name = filename;
module.FileName = filename;
Module m = this.asmREmit.GetModule(moduleName);
if (m == null)
{
ModuleBuilder moduleBuilder = asmREmit.DefineDynamicModule(moduleName,moduleFileName,true);
m = (Module) moduleBuilder;
}
return m;
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Type ResolveRType(RType type)
{
if (type is RTypeDef)
return ResolveRTypeDef((RTypeDef)type);
else
return ResolveRTypeRef((RTypeRef)type);
}
/// <summary>
/// Resolves the RTypeRef into a Type
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Type ResolveRTypeRef(RTypeRef type)
{
int resolutionScope = type.ResolutionScope & 0x00000003;
if (resolutionScope==0x02 || resolutionScope==0x0)
{
Type retType = type.ReflectionType;
if (retType==null)
{
retType =Type.GetType(type.NameWithNameSpace);
if (retType == null)
{
System.Reflection.Assembly asbly;
if (type.Assembly == null) {
// KIRK: Types in the current assembly don't have an assembly set
asbly = Assembly.GetExecutingAssembly();
if (asbly!=null)
retType = asbly.GetType(type.NameWithNameSpace);
if (retType == null) {
foreach (System.Reflection.Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
retType = a.GetType(type.NameWithNameSpace);
if (retType != null) break;
}
}
}
if (retType == null)
{
if (type.NameWithNameSpace.IndexOf("&")>0)
{
//TODO: this is a workaroun until the complete problem is not solved
RType rTempT = this.asmRail.GetType(type.NameWithNameSpace.Substring(0,type.NameWithNameSpace.Length-1));
if (rTempT==null)
rTempT = this.asmRail.RModuleDef.GetType(type.NameWithNameSpace.Substring(0,type.NameWithNameSpace.Length-1));
Type tempT = ResolveRType(rTempT);
retType = this.asmREmit.GetDynamicModule(this.asmRail.RModuleDef.Name).GetType(type.NameWithNameSpace);
}
if (retType == null)
{
throw new NullReferenceException("Type not found");
}
}
}
}
return retType;
}
else if (resolutionScope==0x03)
{
RTypeRef rtr = this.asmRail.GetTypeByToken((type.ResolutionScope>>2));
if (rtr==null)
throw new NullReferenceException("BAD referenced type");
Type referencedType = ResolveRTypeRef(rtr);
//TODO: Check this binding flags
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
Type typeToReturn = referencedType.GetNestedType(type.Name,bindingFlags);
if (typeToReturn==null)
throw new NullReferenceException("Nested type not found");
return typeToReturn;
}
else
{
throw new Exception("Resolution scope error");
}
}
/// <summary>
/// Resolves the RTypeDef into a TypeBuilder
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Type ResolveRTypeDef(RTypeDef type)
{
string typeName = type.FullName;
Type [] moduleTypes = ResolveRModule(this.asmRail.RModuleDef).GetTypes();
Type returnType = null;
for (int i=0;i<moduleTypes.Length;i++)
{
string assemblyQualifiedName = moduleTypes[i].AssemblyQualifiedName;
if (String.CompareOrdinal(typeName,0,assemblyQualifiedName,0,typeName.Length)==0)
{
returnType = moduleTypes[i];
break;
}
}
if (returnType==null)
{
if (this.TypeBuilders == null)
this.TypeBuilders = new Hashtable();
if (this.TypeBuilders.Contains(type.NameWithNameSpace))
returnType = (Type)(this.TypeBuilders[type.NameWithNameSpace]);
if (returnType==null)
{
RType [] rTypeInterfaces = type.GetInterfaces();
Type t = null;
if (type.IsArray)
{
returnType = ResolveRModule(this.asmRail.RModuleDef).GetType(type.NameWithNameSpace) as Type;
}
else if (type.IsNested && type.DeclaringType!=null
&& type.BaseType!=null && type.BaseType.NameWithNameSpace.Equals("System.Enum"))
{
TypeBuilder tParentEnum = (TypeBuilder)ResolveRType(type.DeclaringType);
t = (TypeBuilder)tParentEnum.DefineNestedType(type.Name,
type.Attributes,
typeof(System.Enum), type.TypeSize);
foreach(RFieldDef f in type.GetFields())
{
Type ft;
if (type.FullName.Equals(f.FieldType.FullName))
ft = t;
else
ft = ResolveRType(f.FieldType);
FieldBuilder fb = ((TypeBuilder)t).DefineField(
f.Name,
ft,
f.Attributes);
if ((f.Value != null) && (f.Name != "value__"))
fb.SetConstant(f.Value);
if (f.HasMarshal)
{
if (f.MarshalSpec.GetNativeType() == UnmanagedType.ByValArray)
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineByValArray(f.MarshalSpec.NumElem));
}
else if (f.MarshalSpec.GetNativeType() == UnmanagedType.ByValTStr)
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineByValTStr(f.MarshalSpec.NumElem));
}
else if (f.MarshalSpec.GetNativeType() == UnmanagedType.LPArray)
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineLPArray(f.MarshalSpec.ArrayElementType));
}
else if (f.MarshalSpec.GetNativeType() == UnmanagedType.SafeArray)
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineSafeArray(f.MarshalSpec.ArrayElementType));
}
else
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineUnmanagedMarshal(f.MarshalSpec.GetNativeType()));
}
}
if (f.Offset>0)
((FieldBuilder)fb).SetOffset(f.Offset);
}
}
else if (type.IsNested && type.DeclaringType!=null &&
type.BaseType!=null && type.BaseType.NameWithNameSpace.Equals("System.MulticastDelegate"))
{
TypeBuilder tParentDelegate = (TypeBuilder)ResolveRType(type.DeclaringType);
t = (TypeBuilder)tParentDelegate.DefineNestedType(
type.Name,
type.Attributes,
typeof(System.MulticastDelegate),type.TypeSize);
}
else if (type.IsNested && type.DeclaringType!=null)
{
TypeBuilder tParent = (TypeBuilder)ResolveRType(type.DeclaringType);
t = (TypeBuilder)tParent.DefineNestedType(type.Name,type.Attributes,null,type.TypeSize);
}
else if (type.BaseType!=null && type.BaseType.NameWithNameSpace.Equals("System.Enum"))
{
// ///TODO: There is a problem with the literals attributes, but Reflection.Emit
t = (TypeBuilder)((ModuleBuilder)ResolveRModule(this.asmRail.RModuleDef)).DefineType(type.NameWithNameSpace,
type.Attributes,
typeof(System.Enum), type.TypeSize);
foreach(RFieldDef f in type.GetFields())
{
Type ft;
if (type.FullName.Equals(f.FieldType.FullName))
ft = t;
else
ft = ResolveRType(f.FieldType);
FieldBuilder fb = ((TypeBuilder)t).DefineField(
f.Name,
ft,
f.Attributes);
if ((f.Value != null) && (f.Name != "value__"))
fb.SetConstant(f.Value);
if (f.HasMarshal)
{
if (f.MarshalSpec.GetNativeType() == UnmanagedType.ByValArray)
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineByValArray(f.MarshalSpec.NumElem));
}
else if (f.MarshalSpec.GetNativeType() == UnmanagedType.ByValTStr)
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineByValTStr(f.MarshalSpec.NumElem));
}
else if (f.MarshalSpec.GetNativeType() == UnmanagedType.LPArray)
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineLPArray(f.MarshalSpec.ArrayElementType));
}
else if (f.MarshalSpec.GetNativeType() == UnmanagedType.SafeArray)
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineSafeArray(f.MarshalSpec.ArrayElementType));
}
else
{
((FieldBuilder)fb).SetMarshal(UnmanagedMarshal.DefineUnmanagedMarshal(f.MarshalSpec.GetNativeType()));
}
}
if (f.Offset>0)
((FieldBuilder)fb).SetOffset(f.Offset);
}
}
else if (type.BaseType!=null && type.BaseType.NameWithNameSpace.Equals("System.MulticastDelegate"))
{
t = (TypeBuilder)((ModuleBuilder)ResolveRModule(this.asmRail.RModuleDef)).DefineType(
type.NameWithNameSpace,
type.Attributes,
typeof(System.MulticastDelegate),type.TypeSize);
}
else if ((rTypeInterfaces != null) && (rTypeInterfaces.Length > 0)) {
// KIRK: Added this case to include interfaces in defineType call
Type [] interfaces = new Type[rTypeInterfaces.Length];
for (int i = 0; i< rTypeInterfaces.Length;i++)
interfaces[i] = ResolveRType(rTypeInterfaces[i]);
// This call doesn't have type.TypeSize -- is that a problem???
t = (TypeBuilder)((ModuleBuilder)ResolveRModule(this.asmRail.RModuleDef)).DefineType(
type.NameWithNameSpace,
type.Attributes,null,interfaces);
}
else
{
t = (TypeBuilder)((ModuleBuilder)ResolveRModule(this.asmRail.RModuleDef)).DefineType(
type.NameWithNameSpace,
type.Attributes,null,type.TypeSize);
}
if (t!=null)
{
if (type.BaseType!=null)
if (t is TypeBuilder)
{
((TypeBuilder)t).SetParent(ResolveRType(type.BaseType));
}
if (rTypeInterfaces!=null && t is TypeBuilder)
{
for (int i = 0; i< rTypeInterfaces.Length;i++)
{
((TypeBuilder)t).AddInterfaceImplementation(ResolveRType(rTypeInterfaces[i]));
}
}
returnType = (Type)t;
this.TypeBuilders.Add(type.NameWithNameSpace,t);
}
}
}
return returnType;
}
/// <summary>
///
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
public FieldInfo ResolveRField(RField field)
{
Type fieldType = ResolveRType(field.FieldType);
Type type = (Type)ResolveRType(field.DeclaringType);
BindingFlags bf = (BindingFlags) BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static |
BindingFlags.Instance;
FieldInfo fi = null;
//TODO:Verify if it has beeen created???
if (field is RFieldRef)
fi = type.GetField(field.Name,bf);
else if (field is RFieldDef)
if (fi==null)
{
if (this.FieldBuilders == null)
this.FieldBuilders = new Hashtable();
if (this.FieldBuilders.Contains(field.DeclaringType.NameWithNameSpace+field.Name+field.FieldType.NameWithNameSpace))
fi = (FieldInfo)((FieldBuilder)this.FieldBuilders[field.DeclaringType.NameWithNameSpace+field.Name+field.FieldType.NameWithNameSpace]);
if (fi==null)
{
fi = (FieldInfo)((TypeBuilder)type).DefineField(field.Name,fieldType,field.Attributes);
if (fi!=null)
{
if (field.Value!=null)
try
{
// KIRK: Change int to Enum if necessary
if ((fi.FieldType.UnderlyingSystemType != null) && (fi.FieldType.UnderlyingSystemType.BaseType != null) &&
(fi.FieldType.UnderlyingSystemType.BaseType.FullName == "System.Enum")) {
((FieldBuilder)fi).SetConstant(Enum.ToObject(fi.FieldType.UnderlyingSystemType, field.Value));
} else if ((field.FieldType.BaseType != null) && (field.FieldType.BaseType.NameWithNameSpace == "System.Enum")) {
if (field.FieldType is RTypeRef) {
((FieldBuilder)fi).SetConstant(Convert.ChangeType(field.Value, ((RTypeRef)field.FieldType).reflectionType));
}
} else {
((FieldBuilder)fi).SetConstant(field.Value);
}
}
catch (System.ArgumentException ex)
{
Console.WriteLine("It Was not possible to add a default value to the field");
Console.WriteLine(ex.StackTrace);
}
if (field.HasMarshal)
{
if (field.MarshalSpec.GetNativeType() == UnmanagedType.ByValArray)
{
((FieldBuilder)fi).SetMarshal(UnmanagedMarshal.DefineByValArray(field.MarshalSpec.NumElem));
}
else if (field.MarshalSpec.GetNativeType() == UnmanagedType.ByValTStr)
{
((FieldBuilder)fi).SetMarshal(UnmanagedMarshal.DefineByValTStr(field.MarshalSpec.NumElem));
}
else if (field.MarshalSpec.GetNativeType() == UnmanagedType.LPArray)
{
((FieldBuilder)fi).SetMarshal(UnmanagedMarshal.DefineLPArray(field.MarshalSpec.ArrayElementType));
}
else if (field.MarshalSpec.GetNativeType() == UnmanagedType.SafeArray)
{
((FieldBuilder)fi).SetMarshal(UnmanagedMarshal.DefineSafeArray(field.MarshalSpec.ArrayElementType));
}
else
{
((FieldBuilder)fi).SetMarshal(UnmanagedMarshal.DefineUnmanagedMarshal(field.MarshalSpec.GetNativeType()));
}
}
if (((RFieldDef)field).Offset>0)
((FieldBuilder)fi).SetOffset(((RFieldDef)field).Offset);
}
this.FieldBuilders.Add(field.DeclaringType.NameWithNameSpace+field.Name+field.FieldType.NameWithNameSpace,fi);
}
}
//TODO:Check if it is necessary to get the constant value
return fi;
}
/// <summary>
///
/// </summary>
/// <param name="method"></param>
/// <returns></returns>
public MethodInfo ResolveRMethod(RMethod method)
{
Type type = ResolveRType(method.DeclaringType);
BindingFlags bindingFlags = BindingFlags.Instance
| BindingFlags.NonPublic
| BindingFlags.Public
| BindingFlags.Static;
RParameter [] pt = method.GetParameters();
Type [] paramTypes = null;
if (pt != null)
{
paramTypes = new Type[pt.Length];
for (int i=0; i< pt.Length;i++)
{
paramTypes[i] = ResolveRType(pt[i].ParameterType);
}
}
MethodInfo mi = null;
if (method is RMethodRef){
// KIRK: GetMethod may break if methods only differ by return type
try {
mi = type.GetMethod(method.Name,bindingFlags,null,method.CallingConventions,paramTypes,null);
} catch (AmbiguousMatchException) {
// If there is an ambiguous match, it's probably due to return type overloading
// (e.g. IntPtr.op_Explicit(IntPtr))
MethodInfo[] methods = type.GetMethods(bindingFlags);
foreach (MethodInfo mis in methods) {
if ((mis.Name == method.Name) &&
(mis.ReturnType.FullName == method.ReturnType.ReturnType.NameWithNameSpace)) {
// This might be it - check params
ParameterInfo[] misParams = mis.GetParameters();
RParameter[] methodParams = method.GetParameters();
if (misParams.Length == methodParams.Length) {
bool success = true;
for (int i = 0; i < misParams.Length; i++) {
if (misParams[i].ParameterType.FullName !=
methodParams[i].ParameterType.NameWithNameSpace) {
success = false;
break;
}
}
if (success) {
mi = mis;
break;
}
}
}
}
if (mi == null)
throw;
}
} else if (method is RMethodDef)
if (mi==null)
{
if (this.MethodBuilders == null)
this.MethodBuilders = new Hashtable();
if (this.MethodBuilders.Contains(method.Name+
method.DeclaringType.NameWithNameSpace+
method.ReturnType.ReturnType.NameWithNameSpace+
ParamsToString(paramTypes)))
mi = (MethodInfo)((MethodBuilder)this.MethodBuilders[method.Name+
method.DeclaringType.NameWithNameSpace+
method.ReturnType.ReturnType.NameWithNameSpace+
ParamsToString(paramTypes)]);
if (mi==null)
{
if (method.IsPInvoke)
{
mi = (MethodInfo)((TypeBuilder)type).DefinePInvokeMethod(
method.Name,
method.PInvokeInfo.DLLName,
method.PInvokeInfo.EntryName,
method.Attributes,
method.CallingConventions,
ResolveRType(method.ReturnType.ReturnType),
paramTypes,
method.PInvokeInfo.NativeCallingConvention,
method.PInvokeInfo.NativeCharSet);
}
else
{
mi = (MethodInfo)((TypeBuilder)type).DefineMethod(
method.Name,method.Attributes,
method.CallingConventions,
ResolveRType(method.ReturnType.ReturnType),
paramTypes);
}
RParameter [] rParam = method.GetParameters();
RCustomAttrib rca;
if (rParam!=null)
for (int pIndex=0; pIndex<rParam.Length;pIndex++)
{
RParameter tempParam = rParam[pIndex];
int newSeq = tempParam.Sequence;
if ((mi.Attributes & MethodAttributes.Static)!=0)
++newSeq;
ParameterBuilder pb = ((MethodBuilder)mi).DefineParameter(newSeq,
tempParam.Attributes,tempParam.Name);
if (tempParam.CustomAttributeCount>0)
while (tempParam.MoveToNextCustomAttribute())
{
rca = null;
rca = tempParam.CurrentCustomAttribute;
if (rca!=null && rca.GetAttributeConstructorArguments()!=null)
pb.SetCustomAttribute(ResolveRCustomAttrib(rca));
else if (rca!=null)
{
ConstructorInfo cInfo = ResolveRConstructor(rca.AttributeConstructor) as ConstructorInfo;
pb.SetCustomAttribute(cInfo,rca.AttributeData);
}
}
if (rParam[pIndex].HasMarshal)
{
if (rParam[pIndex].MarshalSpec.GetNativeType() == UnmanagedType.ByValArray)
{
((ParameterBuilder)pb).SetMarshal(UnmanagedMarshal.DefineByValArray(rParam[pIndex].MarshalSpec.NumElem));
}
else if (rParam[pIndex].MarshalSpec.GetNativeType() == UnmanagedType.ByValTStr)
{
((ParameterBuilder)pb).SetMarshal(UnmanagedMarshal.DefineByValTStr(rParam[pIndex].MarshalSpec.NumElem));
}
else if (rParam[pIndex].MarshalSpec.GetNativeType() == UnmanagedType.LPArray)
{
((ParameterBuilder)pb).SetMarshal(UnmanagedMarshal.DefineLPArray(rParam[pIndex].MarshalSpec.ArrayElementType));
}
else if (rParam[pIndex].MarshalSpec.GetNativeType() == UnmanagedType.SafeArray)
{
((ParameterBuilder)pb).SetMarshal(UnmanagedMarshal.DefineSafeArray(rParam[pIndex].MarshalSpec.ArrayElementType));
}
else
{
((ParameterBuilder)pb).SetMarshal(UnmanagedMarshal.DefineUnmanagedMarshal(rParam[pIndex].MarshalSpec.GetNativeType()));
}
}
}
if (mi!=null
&& mi.DeclaringType!=null
&& mi.DeclaringType.BaseType != null
&& mi.DeclaringType.BaseType.FullName.Equals("System.MulticastDelegate"))
((MethodBuilder)mi).SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
this.MethodBuilders.Add(method.Name+
method.DeclaringType.NameWithNameSpace+
method.ReturnType.ReturnType.NameWithNameSpace+
ParamsToString(paramTypes),mi);
}
}
if (mi==null)
throw new NullReferenceException("No MethodInfo found");
return mi;
}
/// <summary>
///
/// </summary>
/// <param name="declaration"></param>
/// <param name="body"></param>
public void DefineMethodOverride(MethodInfo declaration, MethodInfo body)
{
TypeBuilder tb = body.DeclaringType as TypeBuilder;
tb.DefineMethodOverride(body,declaration);
}
/// <summary>
///
/// </summary>
/// <param name="method"></param>
/// <returns></returns>
public ConstructorInfo ResolveRConstructor(RConstructor method)
{
Type type = ResolveRType(method.DeclaringType);
BindingFlags bindingFlags = BindingFlags.NonPublic
| BindingFlags.Public;
ConstructorInfo ci = null;
if ( method.Name == ".ctor" )
{
bindingFlags = BindingFlags.Instance
| BindingFlags.NonPublic
| BindingFlags.Public;
}
else if ( method.Name == ".cctor" )
{
bindingFlags = BindingFlags.Static
| BindingFlags.NonPublic
| BindingFlags.Public;
}
RParameter [] pt = method.GetParameters();
Type [] paramTypes = null;
if (pt != null)
{
paramTypes = new Type[pt.Length];
int j = 0;
for (int i=0; i< pt.Length;i++)
{
//TODO: Verify why a null parameter is appearing
if (pt[i].ParameterType==null)
{
Type [] temp = new Type[paramTypes.Length-1];
for (int x = 0; x < i;x++)
temp[x] = paramTypes[x];
paramTypes = temp;
}
else
{
paramTypes[j] = ResolveRType(pt[i].ParameterType);
j++;
}
}
}
//TODO:Verify if it has beeen created???
if (method is RConstructorRef)
ci = type.GetConstructor(bindingFlags,null, paramTypes,null);
else if (method is RConstructorDef)
if (ci==null)
{
if (this.ConstructorBuilders == null)
this.ConstructorBuilders = new Hashtable();
if (this.ConstructorBuilders.Contains(method.DeclaringType.NameWithNameSpace+
method.Attributes.ToString()+
method.CallingConventions.ToString()+
ParamsToString(paramTypes)))
ci = (ConstructorInfo)((ConstructorBuilder)this.ConstructorBuilders[method.DeclaringType.NameWithNameSpace+
method.Attributes.ToString()+
method.CallingConventions.ToString()+
ParamsToString(paramTypes)]);
if (ci==null)
{
RCustomAttrib rca;
ci = (ConstructorInfo)((TypeBuilder)type).DefineConstructor(method.Attributes,method.CallingConventions,paramTypes);
// KIRK: InternalCall methods don't have (or need) IL for the method body.
// We need to copy MethodImplementationFlags to allow this, but they currently
// aren't preserved by the writer when constructing the new assembly.
if ((method.MethodImplementationFlags & MethodImplAttributes.InternalCall) ==
MethodImplAttributes.InternalCall) {
Type ConstructorBuilderType = typeof(ConstructorBuilder);
FieldInfo mbfi = ConstructorBuilderType.GetField("m_methodBuilder", BindingFlags.Instance | BindingFlags.NonPublic);
MethodBuilder mb = (MethodBuilder)mbfi.GetValue(ci);
Type MethodBuilderType = typeof(MethodBuilder);
FieldInfo iffi = MethodBuilderType.GetField("m_dwMethodImplFlags", BindingFlags.Instance | BindingFlags.NonPublic);
iffi.SetValue(mb, method.MethodImplementationFlags);
}
RParameter [] rParam = method.GetParameters();
if (rParam!=null)
for (int pIndex=0; pIndex<rParam.Length;pIndex++)
{
RParameter tempParam = rParam[pIndex];
ParameterBuilder pb =
((ConstructorBuilder)ci).DefineParameter(tempParam.Sequence,
tempParam.Attributes,tempParam.Name);
if (tempParam.CustomAttributeCount>0)
while (tempParam.MoveToNextCustomAttribute())
{
rca = null;
rca = tempParam.CurrentCustomAttribute;
if (rca!=null && rca.GetAttributeConstructorArguments()!=null)
pb.SetCustomAttribute(ResolveRCustomAttrib(rca));
else if (rca!=null)
{
ConstructorInfo cInfo = ResolveRConstructor(rca.AttributeConstructor) as ConstructorInfo;
pb.SetCustomAttribute(cInfo,rca.AttributeData);
}
}
}
if (ci != null
&& ci.DeclaringType != null
&& ci.DeclaringType.BaseType != null
&& ci.DeclaringType.BaseType.FullName.Equals("System.MulticastDelegate"))
((ConstructorBuilder)ci).SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
this.ConstructorBuilders.Add(method.DeclaringType.NameWithNameSpace+
method.Attributes.ToString()+
method.CallingConventions.ToString()+
ParamsToString(paramTypes),ci);
}
}
if (ci==null)
throw new NullReferenceException("No ConstructorInfo found");
return ci;
}
/// <summary>
///
/// </summary>
/// <param name="types"></param>
/// <returns></returns>
private string ParamsToString(Type [] types)
{
string returnString = "";
if (types!=null)
for (int i = 0; i < types.Length; i++)
{
returnString += types[i].Namespace + "." + types[i].Name + "-";
}
return returnString;
}
/// <summary>
///
/// </summary>
/// <param name="rp"></param>
/// <returns></returns>
// public PropertyBuilder ResolveRProperty(RProperty rp)
// {
// TypeBuilder tb = (TypeBuilder)ResolveRType(rp.DeclaringType);
// Type pt = ResolveRType(rp.PropertyType);
// RParameter [] rParams = rp.GetIndexParameters();
// Type [] parameters = null;
// if (rParams!=null)
// {
// parameters = new Type[rParams.Length];
// for (int i=0;i<rParams.Length;i++)
// {
// parameters[i] = ResolveRType(rParams[i].ParameterType);
// }
// }
// PropertyBuilder propertyBuilder = null;
// if (this.PropertyBuilders==null)
// this.PropertyBuilders = new Hashtable();
// if (this.PropertyBuilders.Contains(rp.Name+
// rp.DeclaringType.NameWithNameSpace+
// rp.PropertyType.NameWithNameSpace))
// propertyBuilder = (PropertyBuilder)this.PropertyBuilders[rp.Name+
// rp.DeclaringType.NameWithNameSpace+
// rp.PropertyType.NameWithNameSpace];
// if (propertyBuilder==null)
// {
// propertyBuilder = tb.DefineProperty(
// rp.Name,
// rp.Attributes,
// pt,
// parameters);
// if (propertyBuilder==null)
// throw new NullReferenceException("RProperty not correctly resolved before setting the methods");
// RMethod rm = rp.GetMethod;
// if (rm!=null)
// {
// MethodBuilder mb = (MethodBuilder)ResolveRMethod(rm);
// propertyBuilder.SetGetMethod(mb);
// }
// rm = null;
// rm = rp.SetMethod;
// if (rm!=null)
// {
// MethodBuilder mb = (MethodBuilder)ResolveRMethod(rm);
// propertyBuilder.SetSetMethod(mb);
// }
// this.PropertyBuilders.Add(rp.Name+
// rp.DeclaringType.NameWithNameSpace+
// rp.PropertyType.NameWithNameSpace,propertyBuilder);
// }
// if (propertyBuilder==null)
// throw new NullReferenceException("RProperty not correctly resolved");
// return propertyBuilder;
// }
public PropertyInfo ResolveRProperty(RProperty rp)
{
Type tb = (Type)ResolveRType(rp.DeclaringType);
Type pt = ResolveRType(rp.PropertyType);
RParameter [] rParams = rp.GetIndexParameters();
Type [] parameters = null;
if (rParams!=null)
{
parameters = new Type[rParams.Length];
for (int i=0;i<rParams.Length;i++)
{
parameters[i] = ResolveRType(rParams[i].ParameterType);
}
}
if (tb is TypeBuilder)
{
PropertyBuilder propertyBuilder = null;
if (this.PropertyBuilders==null)
this.PropertyBuilders = new Hashtable();
if (this.PropertyBuilders.Contains(rp.Name+
rp.DeclaringType.NameWithNameSpace+
rp.PropertyType.NameWithNameSpace))
propertyBuilder = (PropertyBuilder)this.PropertyBuilders[rp.Name+
rp.DeclaringType.NameWithNameSpace+
rp.PropertyType.NameWithNameSpace];
if (propertyBuilder==null)
{
propertyBuilder = ((TypeBuilder)tb).DefineProperty(
rp.Name,
rp.Attributes,
pt,
parameters);
if (propertyBuilder==null)
throw new NullReferenceException("RProperty not correctly resolved before setting the methods");
RMethod rm = rp.GetMethod;
if (rm!=null)
{
MethodBuilder mb = (MethodBuilder)ResolveRMethod(rm);
propertyBuilder.SetGetMethod(mb);
}
rm = null;
rm = rp.SetMethod;
if (rm!=null)
{
MethodBuilder mb = (MethodBuilder)ResolveRMethod(rm);
propertyBuilder.SetSetMethod(mb);
}
this.PropertyBuilders.Add(rp.Name+
rp.DeclaringType.NameWithNameSpace+
rp.PropertyType.NameWithNameSpace,propertyBuilder);
}
if (propertyBuilder==null)
throw new NullReferenceException("RProperty not correctly resolved");
return (PropertyInfo)propertyBuilder;
}
else
{
return tb.GetProperty(rp.Name,pt);
}
}
/// <summary>
///
/// </summary>
/// <param name="re"></param>
/// <returns></returns>
public EventBuilder ResolveREvent(REventDef re)
{
TypeBuilder tb = (TypeBuilder)ResolveRType(re.DeclaringType);
Type et = ResolveRType(re.EventType);
EventBuilder eventBuilder=null;
if (this.EventBuilders==null)
this.EventBuilders = new Hashtable();
if (this.EventBuilders.Contains(re.Name+
re.DeclaringType.NameWithNameSpace+
re.EventType.NameWithNameSpace))
eventBuilder = (EventBuilder)this.EventBuilders[re.Name+
re.DeclaringType.NameWithNameSpace+
re.EventType.NameWithNameSpace];
if (eventBuilder==null)
{
eventBuilder = tb.DefineEvent(
re.Name,
re.Attributes,
et);
if (eventBuilder==null)
throw new NullReferenceException("The REvent was not correctly resolved before setting the methods");
RMethod rm = null;
rm = re.RaiseMethod;
if (rm != null)
{
MethodBuilder mb = (MethodBuilder)ResolveRMethod(rm);
eventBuilder.SetRaiseMethod(mb);
}
rm = null;
rm = re.AddOnMethod;
if (rm != null)
{
MethodBuilder mb = (MethodBuilder)ResolveRMethod(rm);
eventBuilder.SetAddOnMethod(mb);
}
rm = null;
rm = re.RemoveOnMethod;
if (rm != null)
{
MethodBuilder mb = (MethodBuilder)ResolveRMethod(rm);
eventBuilder.SetRemoveOnMethod(mb);
}
this.EventBuilders.Add(re.Name+
re.DeclaringType.NameWithNameSpace+
re.EventType.NameWithNameSpace,eventBuilder);
}
if (eventBuilder==null)
throw new NullReferenceException("The REvent was not correctly resolved");
return eventBuilder;
}
public CustomAttributeBuilder ResolveRCustomAttrib(RCustomAttrib cAttrib)
{
Object [] ConstructorArgs = cAttrib.GetAttributeConstructorArguments();
ConstructorInfo con = ResolveRConstructor(cAttrib.AttributeConstructor);
PropertyInfo[] namedProperties = null;
object[] propertyValues = cAttrib.GetPropertiesValues();
FieldInfo[] namedFields = null;
object[] fieldValues = cAttrib.GetFieldsValues();
RProperty [] properties = cAttrib.GetProperties();
RField [] fields = cAttrib.GetFields();
if (properties!=null &&
properties.Length>0 &&
properties.Length == propertyValues.Length)
{
namedProperties = new PropertyInfo[properties.Length];
int i = 0;
while (i<properties.Length)
{
namedProperties[i] = ResolveRProperty(properties[i]) as PropertyInfo;
++i;
}
}
if (fields!=null &&
fields.Length>0 &&
fields.Length == fieldValues.Length)
{
namedFields = new FieldInfo[fields.Length];
int i = 0;
while (i<fields.Length)
{
namedFields[i] = ResolveRField(fields[i]) as FieldInfo;
++i;
}
}
int j = 0;
if (ConstructorArgs!=null)
while (j<ConstructorArgs.Length)
{
if (ConstructorArgs[j] is RType)
ConstructorArgs[j] = ResolveRType((RType)ConstructorArgs[j]);
++j;
}
CustomAttributeBuilder cAttribBuilder = null;
// KIRK: If con.Attributes is private, we can't create it - so remove the 'private' from the Attributes
if ((con.Attributes & MethodAttributes.Private) == MethodAttributes.Private) {
Type conBuilderType = con.GetType();
object ret = conBuilderType.InvokeMember("m_methodBuilder", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance, null, con, new object[] {});
if (ret != null) {
Type methodBuilderType = ret.GetType();
object attr = methodBuilderType.InvokeMember("m_iAttributes",
BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance,
null,
ret, new object[] {});
if (attr != null) {
FieldInfo fi = methodBuilderType.GetField("m_iAttributes",
BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(ret, con.Attributes ^ MethodAttributes.Private);
}
}
}
if (fieldValues!=null && propertyValues!=null && fieldValues.Length>0 && propertyValues.Length>0)
cAttribBuilder = new CustomAttributeBuilder(con,ConstructorArgs,namedProperties,propertyValues,namedFields,fieldValues);
else if (fieldValues!=null && fieldValues.Length>0)
cAttribBuilder = new CustomAttributeBuilder(con,ConstructorArgs,namedFields,fieldValues);
else if (propertyValues!=null && propertyValues.Length>0)
cAttribBuilder = new CustomAttributeBuilder(con,ConstructorArgs,namedProperties,propertyValues);
else if (ConstructorArgs!=null)
cAttribBuilder = new CustomAttributeBuilder((ConstructorInfo)con,ConstructorArgs);
else
// KIRK: Add a support for a parameterless CustomAttribute constructor
cAttribBuilder = new CustomAttributeBuilder((ConstructorInfo)con, new object[0]);
return cAttribBuilder;
}
}
internal class AssemblyLoader : MarshalByRefObject
{
public Assembly LoadAssemblyByPatialName(string assemblyName)
{
return Assembly.LoadWithPartialName(assemblyName);
}
}
}
|