e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
107 lines
4.5 KiB
C#
107 lines
4.5 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
namespace System.ServiceModel.ComIntegration
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Reflection;
|
|
using System.Reflection.Emit;
|
|
using System.Runtime;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
|
|
class EmitterCache
|
|
{
|
|
static EmitterCache Provider = null;
|
|
static object initLock = new object();
|
|
internal static EmitterCache TypeEmitter
|
|
{
|
|
get
|
|
{
|
|
lock (initLock)
|
|
{
|
|
if (Provider == null)
|
|
{
|
|
EmitterCache localProvider = new EmitterCache();
|
|
Thread.MemoryBarrier();
|
|
Provider = localProvider;
|
|
}
|
|
}
|
|
|
|
if (Provider == null)
|
|
{
|
|
throw Fx.AssertAndThrowFatal("Provider should not be null");
|
|
}
|
|
return Provider;
|
|
}
|
|
}
|
|
|
|
ModuleBuilder DynamicModule;
|
|
AssemblyBuilder assemblyBuilder;
|
|
Dictionary<Type, Type> interfaceToClassMap;
|
|
|
|
private EmitterCache()
|
|
{
|
|
AssemblyName assemblyName = new AssemblyName();
|
|
assemblyName.Name = Guid.NewGuid().ToString();
|
|
assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
|
|
DynamicModule = assemblyBuilder.DefineDynamicModule(Guid.NewGuid().ToString());
|
|
interfaceToClassMap = new Dictionary<Type, Type>();
|
|
}
|
|
private Type[] GetParameterTypes(MethodInfo mInfo)
|
|
{
|
|
ParameterInfo[] parameters = mInfo.GetParameters();
|
|
Type[] typeArray = new Type[parameters.Length];
|
|
int index = 0;
|
|
for (; index < parameters.Length; index++)
|
|
{
|
|
typeArray[index] = parameters[index].ParameterType;
|
|
}
|
|
return typeArray;
|
|
}
|
|
|
|
[SuppressMessage(FxCop.Category.Usage, "CA2301:EmbeddableTypesInContainersRule", MessageId = "interfaceToClassMap", Justification = "No need to support type equivalence here.")]
|
|
internal Type FindOrCreateType(Type interfaceType)
|
|
{
|
|
if (!interfaceType.IsInterface)
|
|
{
|
|
throw Fx.AssertAndThrow("Passed in type should be an Interface");
|
|
}
|
|
Type classType = null;
|
|
lock (this)
|
|
{
|
|
interfaceToClassMap.TryGetValue(interfaceType, out classType);
|
|
if (classType == null)
|
|
{
|
|
TypeBuilder typeBuilder = DynamicModule.DefineType(interfaceType.Name + "MarshalByRefObject", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Abstract,
|
|
typeof(MarshalByRefObject), new Type[] { interfaceType });
|
|
Type[] ctorParams = new Type[] { typeof(ClassInterfaceType) };
|
|
ConstructorInfo classCtorInfo = typeof(ClassInterfaceAttribute).GetConstructor(ctorParams);
|
|
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(classCtorInfo,
|
|
new object[] { ClassInterfaceType.None });
|
|
typeBuilder.SetCustomAttribute(attributeBuilder);
|
|
typeBuilder.AddInterfaceImplementation(interfaceType);
|
|
foreach (MethodInfo mInfo in interfaceType.GetMethods())
|
|
{
|
|
MethodBuilder methodInClass = null;
|
|
methodInClass = typeBuilder.DefineMethod(mInfo.Name,
|
|
MethodAttributes.Public | MethodAttributes.Virtual |
|
|
MethodAttributes.Abstract | MethodAttributes.Abstract | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
|
|
mInfo.ReturnType, GetParameterTypes(mInfo));
|
|
}
|
|
classType = typeBuilder.CreateType();
|
|
interfaceToClassMap[interfaceType] = classType;
|
|
|
|
}
|
|
}
|
|
if (classType == null)
|
|
{
|
|
throw Fx.AssertAndThrow("Class Type should not be null at this point");
|
|
}
|
|
return classType;
|
|
}
|
|
}
|
|
}
|