public Type GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options) { // make sure ProxyGenerationOptions is initialized options.Initialize(); CheckNotGenericTypeDefinition(proxyTargetType, "proxyTargetType"); CheckNotGenericTypeDefinitions(interfaces, "interfaces"); Type generatedType; ReaderWriterLock rwlock = Scope.RWLock; rwlock.AcquireReaderLock(-1); CacheKey cacheKey = new CacheKey(proxyTargetType, targetType, interfaces, options); Type cacheType = GetFromCache(cacheKey); if (cacheType != null) { rwlock.ReleaseReaderLock(); return cacheType; } rwlock.UpgradeToWriterLock(-1); try { cacheType = GetFromCache(cacheKey); if (cacheType != null) { return cacheType; } SetGenerationOptions (options); String newName = targetType.Name + "Proxy" + Guid.NewGuid().ToString("N"); // Add Interfaces that the proxy implements ArrayList interfaceList = new ArrayList(); interfaceList.Add(targetType); if (interfaces != null) { interfaceList.AddRange(interfaces); } if (!interfaceList.Contains(typeof(ISerializable))) interfaceList.Add(typeof(ISerializable)); AddMixinInterfaces(interfaceList); AddDefaultInterfaces(interfaceList); Type baseType = options.BaseTypeForInterfaceProxy; ClassEmitter emitter = BuildClassEmitter(newName, baseType, interfaceList); CreateOptionsField (emitter); emitter.DefineCustomAttribute(new XmlIncludeAttribute(targetType)); emitter.DefineCustomAttribute(new SerializableAttribute()); // Custom attributes ReplicateNonInheritableAttributes(targetType, emitter); // Fields generations FieldReference interceptorsField = emitter.CreateField("__interceptors", typeof(IInterceptor[])); targetField = emitter.CreateField("__target", proxyTargetType); emitter.DefineCustomAttributeFor(interceptorsField, new XmlIgnoreAttribute()); emitter.DefineCustomAttributeFor(targetField, new XmlIgnoreAttribute()); // Implement builtin Interfaces ImplementProxyTargetAccessor(targetType, emitter,interceptorsField); // Collect methods PropertyToGenerate[] propsToGenerate; EventToGenerate[] eventToGenerates; MethodInfo[] methods = CollectMethodsAndProperties(emitter, targetType, out propsToGenerate, out eventToGenerates); if (interfaces != null && interfaces.Length != 0) { ArrayList tmpInterfaces = new ArrayList(interfaces); foreach(Type inter in interfaces) { if (inter.IsAssignableFrom(proxyTargetType)) { PropertyToGenerate[] tempPropsToGenerate; EventToGenerate[] tempEventToGenerates; MethodInfo[] methodsTemp = CollectMethodsAndProperties(emitter, inter, out tempPropsToGenerate, out tempEventToGenerates); PropertyToGenerate[] newPropsToGenerate = new PropertyToGenerate[tempPropsToGenerate.Length + propsToGenerate.Length]; MethodInfo[] newMethods = new MethodInfo[methodsTemp.Length + methods.Length]; EventToGenerate[] newEvents = new EventToGenerate[eventToGenerates.Length + tempEventToGenerates.Length]; Array.Copy(methods, newMethods, methods.Length); Array.Copy(methodsTemp, 0, newMethods, methods.Length, methodsTemp.Length); Array.Copy(propsToGenerate, newPropsToGenerate, propsToGenerate.Length); Array.Copy(tempPropsToGenerate, 0, newPropsToGenerate, propsToGenerate.Length, tempPropsToGenerate.Length); Array.Copy(eventToGenerates, newEvents, eventToGenerates.Length); Array.Copy(tempEventToGenerates, 0, newEvents, eventToGenerates.Length, tempEventToGenerates.Length); methods = newMethods; propsToGenerate = newPropsToGenerate; eventToGenerates = newEvents; tmpInterfaces.Remove(inter); } } interfaces = (Type[]) tmpInterfaces.ToArray(typeof(Type)); } RegisterMixinMethodsAndProperties(emitter, ref methods, ref propsToGenerate, ref eventToGenerates); options.Hook.MethodsInspected(); // Constructor ConstructorEmitter typeInitializer = GenerateStaticConstructor(emitter); if (!proxyTargetType.IsInterface) { CacheMethodTokens(emitter, MethodFinder.GetAllInstanceMethods(proxyTargetType, BindingFlags.Public | BindingFlags.Instance), typeInitializer); } CreateInitializeCacheMethodBody(proxyTargetType, methods, emitter, typeInitializer); FieldReference[] mixinFields = AddMixinFields(emitter); List<FieldReference> fields = new List<FieldReference>(mixinFields); fields.Add(interceptorsField); fields.Add(targetField); GenerateConstructors(emitter, baseType, fields.ToArray()); // GenerateParameterlessConstructor(emitter, interceptorsField, baseType); // Implement interfaces if (interfaces != null && interfaces.Length != 0) { foreach(Type inter in interfaces) { ImplementBlankInterface(targetType, inter, emitter, interceptorsField, typeInitializer); } } // Create invocation types foreach(MethodInfo method in methods) { CreateInvocationForMethod(emitter, method, proxyTargetType); } // Create methods overrides Dictionary<MethodInfo, MethodEmitter> method2Emitter = new Dictionary<MethodInfo, MethodEmitter>(); foreach(MethodInfo method in methods) { if (method.IsSpecialName && (method.Name.StartsWith("get_") || method.Name.StartsWith("set_") || method.Name.StartsWith("add_") || method.Name.StartsWith("remove_")) || methodsToSkip.Contains(method)) { continue; } NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[method]; MethodEmitter newProxiedMethod = CreateProxiedMethod( targetType, method, emitter, nestedClass, interceptorsField, GetTargetRef(method, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[method]); ReplicateNonInheritableAttributes(method, newProxiedMethod); method2Emitter[method] = newProxiedMethod; } foreach(PropertyToGenerate propToGen in propsToGenerate) { if (propToGen.CanRead) { NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[propToGen.GetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.GetMethod); MethodEmitter getEmitter = propToGen.Emitter.CreateGetMethod(atts); ImplementProxiedMethod(targetType, getEmitter, propToGen.GetMethod, emitter, nestedClass, interceptorsField, GetTargetRef(propToGen.GetMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[propToGen.GetMethod]); ReplicateNonInheritableAttributes(propToGen.GetMethod, getEmitter); // emitter.TypeBuilder.DefineMethodOverride(getEmitter.MethodBuilder, propToGen.GetMethod); } if (propToGen.CanWrite) { NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[propToGen.SetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.SetMethod); MethodEmitter setEmitter = propToGen.Emitter.CreateSetMethod(atts); ImplementProxiedMethod(targetType, setEmitter, propToGen.SetMethod, emitter, nestedClass, interceptorsField, GetTargetRef(propToGen.SetMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[propToGen.SetMethod]); ReplicateNonInheritableAttributes(propToGen.SetMethod, setEmitter); // emitter.TypeBuilder.DefineMethodOverride(setEmitter.MethodBuilder, propToGen.SetMethod); } } foreach(EventToGenerate eventToGenerate in eventToGenerates) { NestedClassEmitter add_nestedClass = (NestedClassEmitter) method2Invocation[eventToGenerate.AddMethod]; MethodAttributes add_atts = ObtainMethodAttributes(eventToGenerate.AddMethod); MethodEmitter addEmitter = eventToGenerate.Emitter.CreateAddMethod(add_atts); ImplementProxiedMethod(targetType, addEmitter, eventToGenerate.AddMethod, emitter, add_nestedClass, interceptorsField, GetTargetRef(eventToGenerate.AddMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[eventToGenerate.AddMethod]); ReplicateNonInheritableAttributes(eventToGenerate.AddMethod, addEmitter); NestedClassEmitter remove_nestedClass = (NestedClassEmitter) method2Invocation[eventToGenerate.RemoveMethod]; MethodAttributes remove_atts = ObtainMethodAttributes(eventToGenerate.RemoveMethod); MethodEmitter removeEmitter = eventToGenerate.Emitter.CreateRemoveMethod(remove_atts); ImplementProxiedMethod(targetType, removeEmitter, eventToGenerate.RemoveMethod, emitter, remove_nestedClass, interceptorsField, GetTargetRef(eventToGenerate.RemoveMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[eventToGenerate.RemoveMethod]); ReplicateNonInheritableAttributes(eventToGenerate.RemoveMethod, removeEmitter); } ImplementGetObjectData(emitter, interceptorsField, mixinFields, interfaces); // Complete Initialize CompleteInitCacheMethod(typeInitializer.CodeBuilder); // Crosses fingers and build type generatedType = emitter.BuildType(); InitializeStaticFields (generatedType); /*foreach (MethodInfo m in TypeFinder.GetMethods(generatedType, BindingFlags.Instance | BindingFlags.Public)) { ParameterInfo[] parameters = m.GetParameters(); // Console.WriteLine(m.Name); for (int i = 0; i < parameters.Length; i++) { ParameterInfo paramInfo = parameters[i]; // Console.WriteLine("{0} {1} {2} {3}", paramInfo.Name, paramInfo.ParameterType, paramInfo.Attributes, paramInfo.Position); // Console.WriteLine("{0} {1} {2} {3}", paramInfo2.Name, paramInfo2.ParameterType, paramInfo2.Attributes, paramInfo2.Position); } } */ AddToCache(cacheKey, generatedType); } finally { rwlock.ReleaseWriterLock(); } return generatedType; }
private EventToGenerate[] CollectEvents(ArrayList methodList, Type type, bool onlyVirtuals, ClassEmitter emitter) { ArrayList toGenerateList = new ArrayList(); BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; EventInfo[] events = type.GetEvents(flags); foreach(EventInfo eventInfo in events) { MethodInfo addMethod = eventInfo.GetAddMethod(true); MethodInfo removeMethod = eventInfo.GetRemoveMethod(true); bool shouldGenerate = false; if (addMethod != null && IsAccessible(addMethod) && AcceptMethod(addMethod, onlyVirtuals)) { shouldGenerate = true; methodList.Add(addMethod); } if (removeMethod != null && IsAccessible(removeMethod) && AcceptMethod(removeMethod, onlyVirtuals)) { shouldGenerate = true; methodList.Add(removeMethod); } if (shouldGenerate == false) continue; EventAttributes atts = ObtainEventAttributes(eventInfo); EventEmitter eventEmitter = emitter.CreateEvent(eventInfo.Name, atts, eventInfo.EventHandlerType); EventToGenerate eventToGenerate = new EventToGenerate(eventEmitter, addMethod, removeMethod, atts); toGenerateList.Add(eventToGenerate); } return (EventToGenerate[]) toGenerateList.ToArray(typeof(EventToGenerate)); }
private void CollectEventMethodsToProxy( ArrayList methodList, Type type, bool onlyVirtuals, ClassEmitter emitter, out EventToGenerate[] eventsToGenerates) { if (type.IsInterface) { ArrayList toGenerateList = new ArrayList(); toGenerateList.AddRange(CollectEvents(methodList, type, onlyVirtuals, emitter)); Type[] typeChain = type.FindInterfaces(new TypeFilter(NoFilter), null); foreach(Type interType in typeChain) { toGenerateList.AddRange(CollectEvents(methodList, interType, onlyVirtuals, emitter)); } eventsToGenerates = (EventToGenerate[]) toGenerateList.ToArray(typeof(EventToGenerate)); } else { eventsToGenerates = CollectEvents(methodList, type, onlyVirtuals, emitter); } }
protected MethodInfo[] CollectMethodsAndProperties( ClassEmitter emitter, Type targetType, bool onlyVirtuals, out PropertyToGenerate[] propsToGenerate, out EventToGenerate[] eventsToGenerate) { ArrayList methodsList = new ArrayList(); CollectMethodsToProxy(methodsList, targetType, onlyVirtuals); CollectPropertyMethodsToProxy(methodsList, targetType, onlyVirtuals, emitter, out propsToGenerate); CollectEventMethodsToProxy(methodsList, targetType, onlyVirtuals, emitter, out eventsToGenerate); return (MethodInfo[]) methodsList.ToArray(typeof(MethodInfo)); }
protected MethodInfo[] CollectMethodsAndProperties( ClassEmitter emitter, Type targetType, out PropertyToGenerate[] propsToGenerate, out EventToGenerate[] eventsToGenerate) { bool onlyVirtuals = CanOnlyProxyVirtual(); return CollectMethodsAndProperties(emitter, targetType, onlyVirtuals, out propsToGenerate, out eventsToGenerate); }
protected void RegisterMixinMethodsAndProperties(ClassEmitter emitter, ref MethodInfo[] methods, ref PropertyToGenerate[] propsToGenerate, ref EventToGenerate[] eventsToGenerate) { List<MethodInfo> withMixinMethods = new List<MethodInfo>(methods); List<PropertyToGenerate> withMixinProperties = null; List<EventToGenerate> withMixinEvents = null; foreach (Type mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfacesAndPositions.Keys) { PropertyToGenerate[] mixinPropsToGenerate; EventToGenerate[] mixinEventsToGenerate; MethodInfo[] mixinMethods = CollectMethodsAndProperties(emitter, mixinInterface, false, out mixinPropsToGenerate, out mixinEventsToGenerate); foreach (MethodInfo mixinMethod in mixinMethods) { if (!method2MixinType.ContainsKey(mixinMethod)) { method2MixinType[mixinMethod] = mixinInterface; withMixinMethods.Add(mixinMethod); } } if (mixinPropsToGenerate.Length > 0) { if (withMixinProperties == null) { withMixinProperties = new List<PropertyToGenerate>(propsToGenerate); } withMixinProperties.AddRange(mixinPropsToGenerate); } if (mixinEventsToGenerate.Length > 0) { if (withMixinEvents == null) { withMixinEvents = new List<EventToGenerate>(eventsToGenerate); } withMixinEvents.AddRange(mixinEventsToGenerate); } } if (withMixinMethods != null) { methods = withMixinMethods.ToArray(); } if (withMixinProperties != null) { propsToGenerate = withMixinProperties.ToArray(); } if (withMixinEvents != null) { eventsToGenerate = withMixinEvents.ToArray(); } }