PageRenderTime 43ms CodeModel.GetById 16ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 1ms

/Source/Bifrost.Silverlight/Notification/NotifyingObjectWeaver.cs

#
C# | 496 lines | 388 code | 80 blank | 28 comment | 14 complexity | ef99f676cf2e8617acdc831bfcfad5ab MD5 | raw file
  1#region License
  2//
  3// Copyright (c) 2008-2012, DoLittle Studios and Komplett ASA
  4//
  5// Licensed under the Microsoft Permissive License (Ms-PL), Version 1.1 (the "License")
  6// With one exception :
  7//   Commercial libraries that is based partly or fully on Bifrost and is sold commercially, 
  8//   must obtain a commercial license.
  9//
 10// You may not use this file except in compliance with the License.
 11// You may obtain a copy of the license at 
 12//
 13//   http://bifrost.codeplex.com/license
 14//
 15// Unless required by applicable law or agreed to in writing, software
 16// distributed under the License is distributed on an "AS IS" BASIS,
 17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 18// See the License for the specific language governing permissions and
 19// limitations under the License.
 20//
 21#endregion
 22#if(SILVERLIGHT)
 23using System;
 24using System.Collections.Generic;
 25using System.ComponentModel;
 26using System.Linq;
 27using System.Linq.Expressions;
 28using System.Reflection;
 29using System.Reflection.Emit;
 30using System.Threading;
 31using System.Xml.Serialization;
 32
 33namespace Bifrost.Notification
 34{
 35	public class NotifyingObjectWeaver
 36	{
 37		private const string DynamicAssemblyName = "Dynamic Assembly";
 38		private const string DynamicModuleName = "Dynamic Module";
 39		private const string PropertyChangedEventName = "PropertyChanged";
 40		private const string OnPropertyChangedMethodName = "OnPropertyChanged";
 41		private const string DispatcherFieldName = "Dispatcher";
 42		private const string DispatcherManagerCurrentPropertyName = "Current";
 43
 44		private static readonly Type VoidType = typeof(void);
 45		private static readonly Type DelegateType = typeof(Delegate);
 46
 47		private const MethodAttributes EventMethodAttributes =
 48			MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
 49
 50		private const MethodAttributes OnPropertyChangedMethodAttributes =
 51			MethodAttributes.Public | MethodAttributes.HideBySig;
 52
 53
 54		private static readonly AssemblyBuilder DynamicAssembly;
 55		private static readonly ModuleBuilder DynamicModule;
 56
 57		private static readonly Dictionary<Type, Type> Proxies = new Dictionary<Type, Type>();
 58
 59		static NotifyingObjectWeaver()
 60		{
 61			var dynamicAssemblyName = CreateUniqueName(DynamicAssemblyName);
 62			var dynamicModuleName = CreateUniqueName(DynamicModuleName);
 63			var appDomain = Thread.GetDomain();
 64			var assemblyName = new AssemblyName(dynamicAssemblyName);
 65			DynamicAssembly = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
 66			DynamicModule = DynamicAssembly.DefineDynamicModule(dynamicModuleName, true);
 67		}
 68
 69		public static void ClearTypeCache()
 70		{
 71			Proxies.Clear();
 72		}
 73
 74		public Type GetProxyType<T>()
 75		{
 76			var type = typeof(T);
 77			var proxyType = GetProxyType(type);
 78			return proxyType;
 79		}
 80
 81		public Type GetProxyType(Type type)
 82		{
 83
 84			Type proxyType;
 85			if (Proxies.ContainsKey(type))
 86			{
 87				proxyType = Proxies[type];
 88			}
 89			else
 90			{
 91				proxyType = CreateProxyType(type);
 92				Proxies[type] = proxyType;
 93			}
 94
 95			return proxyType;
 96		}
 97
 98		private static Type CreateProxyType(Type type)
 99		{
100			var typeBuilder = DefineType(type);
101			var eventHandlerType = typeof(PropertyChangedEventHandler);
102
103			AddAttributesToType(type,typeBuilder);
104
105			var propertyChangedFieldBuilder = typeBuilder.DefineField(PropertyChangedEventName, eventHandlerType, FieldAttributes.Private);
106			var dispatcherFieldBuilder = typeBuilder.DefineField(DispatcherFieldName, typeof(IDispatcher),
107																 FieldAttributes.Private | FieldAttributes.Static);
108
109			
110
111			DefineTypeInitializer(type, typeBuilder, dispatcherFieldBuilder);
112			DefineConstructorIfNoDefaultConstructorOnBaseType(type, typeBuilder);
113			OverrideToStringIfNotOverridenInBaseType(type, typeBuilder);
114
115			DefineEvent(typeBuilder, eventHandlerType, propertyChangedFieldBuilder);
116			var onPropertyChangedMethodBuilder = DefineOnPropertyChangedMethod(typeBuilder, eventHandlerType, propertyChangedFieldBuilder, dispatcherFieldBuilder);
117
118
119			DefineProperties(typeBuilder, type, onPropertyChangedMethodBuilder);
120
121			var proxyType = typeBuilder.CreateType();
122			return proxyType;
123		}
124
125		private static void AddAttributesToType(Type type, TypeBuilder typeBuilder)
126		{
127			AddAttributeToType<XmlRootAttribute>(typeBuilder,
128				new Dictionary<string, object>() { { "ElementName", type.Name } });
129			/*
130			AddAttributeToType<DataContractAttribute>(typeBuilder,
131				new Dictionary<string, object>() { { "Name", type.Name } });*/
132		}
133
134		private static void AddAttributeToType<T>(TypeBuilder typeBuilder, IDictionary<string, object> propertiesWithValues)
135			where T : Attribute
136		{
137			var attributeType = typeof (T);
138			var constructor = attributeType.GetConstructor(new Type[0]);
139
140			var properties = new List<PropertyInfo>();
141			var values = new List<object>();
142
143			foreach (var propertyName in propertiesWithValues.Keys)
144			{
145				var property = attributeType.GetProperty(propertyName);
146				properties.Add(property);
147				values.Add(propertiesWithValues[propertyName]);
148			}
149
150			var attributeBuilder =
151				new CustomAttributeBuilder(
152					constructor,
153					new object[0],
154					properties.ToArray(),
155					values.ToArray());
156
157			typeBuilder.SetCustomAttribute(attributeBuilder);
158		}
159
160
161		private static void OverrideToStringIfNotOverridenInBaseType(Type type, TypeBuilder typeBuilder)
162		{
163			var toStringMethod = type.GetMethod("ToString");
164			if ((toStringMethod.Attributes & MethodAttributes.VtableLayoutMask) == MethodAttributes.VtableLayoutMask)
165			{
166				var fullName = type.FullName;
167
168				var newToStringMethod = typeBuilder.DefineMethod("ToString", toStringMethod.Attributes^MethodAttributes.VtableLayoutMask, typeof(string),
169																new Type[0]);
170
171				var toStringBuilder = newToStringMethod.GetILGenerator();
172				toStringBuilder.DeclareLocal(typeof (string));
173				toStringBuilder.Emit(OpCodes.Nop);
174				toStringBuilder.Emit(OpCodes.Ldstr,fullName);
175				toStringBuilder.Emit(OpCodes.Stloc_0);
176				toStringBuilder.Emit(OpCodes.Ldloc_0);
177				toStringBuilder.Emit(OpCodes.Ret);
178
179				typeBuilder.DefineMethodOverride(newToStringMethod,toStringMethod);
180			}
181		}
182
183
184		private static void DefineTypeInitializer(Type type, TypeBuilder typeBuilder, FieldBuilder dispatcherFieldBuilder)
185		{
186			var constructorBuilder = typeBuilder.DefineTypeInitializer();
187			var constructorGenerator = constructorBuilder.GetILGenerator();
188
189			var dispatcherManagerType = typeof(DispatcherManager);
190			var currentGetCurrentMethodName = string.Format("get_{0}", DispatcherManagerCurrentPropertyName);
191			var dispatcherGetCurrentMethod = dispatcherManagerType.GetMethod(currentGetCurrentMethodName);
192
193			constructorGenerator.Emit(OpCodes.Call, dispatcherGetCurrentMethod);
194			constructorGenerator.Emit(OpCodes.Stsfld, dispatcherFieldBuilder);
195			constructorGenerator.Emit(OpCodes.Ret);
196		}
197
198
199		private static void DefineConstructorIfNoDefaultConstructorOnBaseType(Type type, TypeBuilder typeBuilder)
200		{
201			var constructors = type.GetConstructors();
202			if (constructors.Length == 1 && constructors[0].GetParameters().Length == 0)
203			{
204				DefineDefaultConstructor(type, typeBuilder);
205				return;
206			}
207
208			foreach (var constructor in constructors)
209			{
210				var parameters = constructor.GetParameters().Select(p => p.ParameterType).ToArray();
211				var constructorBuilder = typeBuilder.DefineConstructor(constructor.Attributes, constructor.CallingConvention, parameters);
212				var constructorGenerator = constructorBuilder.GetILGenerator();
213				constructorGenerator.Emit(OpCodes.Ldarg_0);
214
215				for (var index = 0; index < parameters.Length; index++)
216				{
217					constructorGenerator.Emit(OpCodes.Ldarg, index + 1);
218				}
219				constructorGenerator.Emit(OpCodes.Call, constructor);
220				constructorGenerator.Emit(OpCodes.Nop);
221				constructorGenerator.Emit(OpCodes.Nop);
222				constructorGenerator.Emit(OpCodes.Nop);
223				constructorGenerator.Emit(OpCodes.Ret);
224			}
225		}
226
227		private static void DefineDefaultConstructor(Type type, TypeBuilder typeBuilder)
228		{
229			typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
230		}
231
232		private static void DefineProperties(TypeBuilder typeBuilder, Type baseType, MethodBuilder onPropertyChangedMethodBuilder)
233		{
234			var properties = baseType.GetProperties();
235			var query = from p in properties
236						where p.GetGetMethod().IsVirtual && !p.GetGetMethod().IsFinal
237						select p;
238
239			var virtualProperties = query.ToArray();
240			foreach (var property in virtualProperties)
241			{
242
243				if (ShouldPropertyBeIgnored(property))
244				{
245					continue;
246				}
247				DefineGetMethodForProperty(property, typeBuilder);
248				DefineSetMethodForProperty(property, typeBuilder, onPropertyChangedMethodBuilder);
249			}
250		}
251
252		private static bool ShouldPropertyBeIgnored(PropertyInfo propertyInfo)
253		{
254			var attributes = propertyInfo.GetCustomAttributes(typeof(IgnoreChangesAttribute), true);
255			return attributes.Length == 1;
256		}
257
258		private static void DefineSetMethodForProperty(PropertyInfo property, TypeBuilder typeBuilder, MethodBuilder onPropertyChangedMethodBuilder)
259		{
260			var setMethodToOverride = property.GetSetMethod();
261			if (null == setMethodToOverride)
262			{
263				return;
264			}
265			var setMethodBuilder = typeBuilder.DefineMethod(setMethodToOverride.Name, setMethodToOverride.Attributes, VoidType, new[] { property.PropertyType });
266			var setMethodGenerator = setMethodBuilder.GetILGenerator();
267			var propertiesToNotifyFor = GetPropertiesToNotifyFor(property);
268
269
270			setMethodGenerator.Emit(OpCodes.Nop);
271			setMethodGenerator.Emit(OpCodes.Ldarg_0);
272			setMethodGenerator.Emit(OpCodes.Ldarg_1);
273			setMethodGenerator.Emit(OpCodes.Call, setMethodToOverride);
274
275			foreach (var propertyName in propertiesToNotifyFor)
276			{
277				setMethodGenerator.Emit(OpCodes.Ldarg_0);
278				setMethodGenerator.Emit(OpCodes.Ldstr, propertyName);
279				setMethodGenerator.Emit(OpCodes.Call, onPropertyChangedMethodBuilder);
280			}
281
282			setMethodGenerator.Emit(OpCodes.Nop);
283			setMethodGenerator.Emit(OpCodes.Ret);
284			typeBuilder.DefineMethodOverride(setMethodBuilder, setMethodToOverride);
285		}
286
287		private static string[] GetPropertiesToNotifyFor(PropertyInfo property)
288		{
289			var properties = new List<string>();
290			properties.Add(property.Name);
291
292			var attributes = property.GetCustomAttributes(typeof(NotifyChangesForAttribute), true);
293			foreach (NotifyChangesForAttribute attribute in attributes)
294			{
295				foreach (var propertyName in attribute.PropertyNames)
296				{
297					properties.Add(propertyName);
298				}
299			}
300			return properties.ToArray();
301		}
302
303		private static void DefineGetMethodForProperty(PropertyInfo property, TypeBuilder typeBuilder)
304		{
305			var getMethodToOverride = property.GetGetMethod();
306			var getMethodBuilder = typeBuilder.DefineMethod(getMethodToOverride.Name, getMethodToOverride.Attributes, property.PropertyType, new Type[0]);
307			var getMethodGenerator = getMethodBuilder.GetILGenerator();
308			var label = getMethodGenerator.DefineLabel();
309
310			getMethodGenerator.DeclareLocal(property.PropertyType);
311			getMethodGenerator.Emit(OpCodes.Nop);
312			getMethodGenerator.Emit(OpCodes.Ldarg_0);
313			getMethodGenerator.Emit(OpCodes.Call, getMethodToOverride);
314			getMethodGenerator.Emit(OpCodes.Stloc_0);
315			getMethodGenerator.Emit(OpCodes.Br_S, label);
316			getMethodGenerator.MarkLabel(label);
317			getMethodGenerator.Emit(OpCodes.Ldloc_0);
318			getMethodGenerator.Emit(OpCodes.Ret);
319			typeBuilder.DefineMethodOverride(getMethodBuilder, getMethodToOverride);
320		}
321
322
323		private static void DefineEvent(TypeBuilder typeBuilder, Type eventHandlerType, FieldBuilder fieldBuilder)
324		{
325			var eventBuilder = typeBuilder.DefineEvent("PropertyChanged", EventAttributes.None, eventHandlerType);
326			DefineAddMethodForEvent(typeBuilder, eventHandlerType, fieldBuilder, eventBuilder);
327			DefineRemoveMethodForEvent(typeBuilder, eventHandlerType, fieldBuilder, eventBuilder);
328		}
329
330		private static void DefineRemoveMethodForEvent(TypeBuilder typeBuilder, Type eventHandlerType, FieldBuilder fieldBuilder, EventBuilder eventBuilder)
331		{
332			var removeEventMethod = string.Format("remove_{0}", PropertyChangedEventName);
333			var removeMethodInfo = DelegateType.GetMethod("Remove", BindingFlags.Public | BindingFlags.Static, null,
334														  new[] { DelegateType, DelegateType }, null);
335			var removeMethodBuilder = typeBuilder.DefineMethod(removeEventMethod, EventMethodAttributes, VoidType, new[] { eventHandlerType });
336			var removeMethodGenerator = removeMethodBuilder.GetILGenerator();
337			removeMethodGenerator.Emit(OpCodes.Ldarg_0);
338			removeMethodGenerator.Emit(OpCodes.Ldarg_0);
339			removeMethodGenerator.Emit(OpCodes.Ldfld, fieldBuilder);
340			removeMethodGenerator.Emit(OpCodes.Ldarg_1);
341			removeMethodGenerator.EmitCall(OpCodes.Call, removeMethodInfo, null);
342			removeMethodGenerator.Emit(OpCodes.Castclass, eventHandlerType);
343			removeMethodGenerator.Emit(OpCodes.Stfld, fieldBuilder);
344			removeMethodGenerator.Emit(OpCodes.Ret);
345			eventBuilder.SetAddOnMethod(removeMethodBuilder);
346		}
347
348		private static void DefineAddMethodForEvent(TypeBuilder typeBuilder, Type eventHandlerType, FieldBuilder fieldBuilder, EventBuilder eventBuilder)
349		{
350			var combineMethodInfo = DelegateType.GetMethod("Combine", BindingFlags.Public | BindingFlags.Static, null,
351														   new[] { DelegateType, DelegateType }, null);
352
353
354			var addEventMethod = string.Format("add_{0}", PropertyChangedEventName);
355			var addMethodBuilder = typeBuilder.DefineMethod(addEventMethod, EventMethodAttributes, VoidType, new[] { eventHandlerType });
356			var addMethodGenerator = addMethodBuilder.GetILGenerator();
357			addMethodGenerator.Emit(OpCodes.Ldarg_0);
358			addMethodGenerator.Emit(OpCodes.Ldarg_0);
359			addMethodGenerator.Emit(OpCodes.Ldfld, fieldBuilder);
360			addMethodGenerator.Emit(OpCodes.Ldarg_1);
361			addMethodGenerator.EmitCall(OpCodes.Call, combineMethodInfo, null);
362			addMethodGenerator.Emit(OpCodes.Castclass, eventHandlerType);
363			addMethodGenerator.Emit(OpCodes.Stfld, fieldBuilder);
364			addMethodGenerator.Emit(OpCodes.Ret);
365			eventBuilder.SetAddOnMethod(addMethodBuilder);
366		}
367
368		private static MethodInfo GetMethodInfoFromType<T>(Expression<Action<T>> expression)
369		{
370			if (expression.Body is MethodCallExpression)
371			{
372				var methodCallExpresion = expression.Body as MethodCallExpression;
373				return methodCallExpresion.Method;
374			}
375			return null;
376		}
377
378		private static MethodBuilder DefineOnPropertyChangedMethod(TypeBuilder typeBuilder, Type eventHandlerType, FieldBuilder propertyChangedFieldBuilder, FieldBuilder dispatcherFieldBuilder)
379		{
380			var propertyChangedEventArgsType = typeof(PropertyChangedEventArgs);
381
382			var onPropertyChangedMethodBuilder = typeBuilder.DefineMethod(OnPropertyChangedMethodName, OnPropertyChangedMethodAttributes, VoidType,
383																		  new[] { typeof(string) });
384			var onPropertyChangedMethodGenerator = onPropertyChangedMethodBuilder.GetILGenerator();
385
386			var checkAccessMethod = GetMethodInfoFromType<IDispatcher>(d => d.CheckAccess());
387			var invokeMethod = GetMethodInfoFromType<PropertyChangedEventHandler>(e => e.Invoke(null, null));
388			var beginInvokeMethod = GetMethodInfoFromType<IDispatcher>(d => d.BeginInvoke(null, null, null));
389
390			var propertyChangedNullLabel = onPropertyChangedMethodGenerator.DefineLabel();
391			var checkAccessFalseLabel = onPropertyChangedMethodGenerator.DefineLabel();
392			var doneLabel = onPropertyChangedMethodGenerator.DefineLabel();
393
394			onPropertyChangedMethodGenerator.DeclareLocal(typeof(PropertyChangedEventArgs));
395			onPropertyChangedMethodGenerator.DeclareLocal(typeof(bool));
396			onPropertyChangedMethodGenerator.DeclareLocal(typeof(object[]));
397			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
398
399			// if( null != PropertyChanged )
400			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldnull);
401			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldarg_0);
402			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldfld, propertyChangedFieldBuilder);
403			onPropertyChangedMethodGenerator.Emit(OpCodes.Ceq);
404			onPropertyChangedMethodGenerator.Emit(OpCodes.Stloc_1);
405			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldloc_1);
406			onPropertyChangedMethodGenerator.Emit(OpCodes.Brtrue_S, propertyChangedNullLabel);
407
408			// args = new PropertyChangedEventArgs()
409			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
410			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldarg_1);
411			onPropertyChangedMethodGenerator.Emit(OpCodes.Newobj, propertyChangedEventArgsType.GetConstructor(new[] { typeof(string) }));
412			onPropertyChangedMethodGenerator.Emit(OpCodes.Stloc_0);
413
414			// if( Dispatcher.CheckAccess() ) 
415			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldsfld, dispatcherFieldBuilder);
416			onPropertyChangedMethodGenerator.Emit(OpCodes.Callvirt, checkAccessMethod);
417			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldc_I4_0);
418			onPropertyChangedMethodGenerator.Emit(OpCodes.Ceq);
419			onPropertyChangedMethodGenerator.Emit(OpCodes.Stloc_1);
420			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldloc_1);
421			onPropertyChangedMethodGenerator.Emit(OpCodes.Brtrue_S, checkAccessFalseLabel);
422
423			// CheckAccess == true
424
425			// Invoke
426			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
427			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldarg_0);
428			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldfld, propertyChangedFieldBuilder);
429			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldarg_0);
430			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldloc_0);
431			onPropertyChangedMethodGenerator.EmitCall(OpCodes.Callvirt, invokeMethod, null);
432			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
433			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
434			onPropertyChangedMethodGenerator.Emit(OpCodes.Br_S, doneLabel);
435
436			// CheckAccess == false
437			onPropertyChangedMethodGenerator.MarkLabel(checkAccessFalseLabel);
438			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
439			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldsfld, dispatcherFieldBuilder);
440			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldarg_0);
441			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldfld, propertyChangedFieldBuilder);
442			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldc_I4_2);
443			onPropertyChangedMethodGenerator.Emit(OpCodes.Newarr, typeof(object));
444			onPropertyChangedMethodGenerator.Emit(OpCodes.Stloc_2);
445			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldloc_2);
446			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldc_I4_0);
447			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldarg_0);
448			onPropertyChangedMethodGenerator.Emit(OpCodes.Stelem_Ref);
449			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldloc_2);
450			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldc_I4_1);
451			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldloc_0);
452			onPropertyChangedMethodGenerator.Emit(OpCodes.Stelem_Ref);
453			onPropertyChangedMethodGenerator.Emit(OpCodes.Ldloc_2);
454			onPropertyChangedMethodGenerator.Emit(OpCodes.Callvirt, beginInvokeMethod);
455			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
456			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
457
458			onPropertyChangedMethodGenerator.MarkLabel(propertyChangedNullLabel);
459			onPropertyChangedMethodGenerator.Emit(OpCodes.Nop);
460			onPropertyChangedMethodGenerator.MarkLabel(doneLabel);
461			onPropertyChangedMethodGenerator.Emit(OpCodes.Ret);
462			return onPropertyChangedMethodBuilder;
463		}
464
465		private static TypeBuilder DefineType(Type type)
466		{
467			var name = CreateUniqueName(type.Name);
468			var typeBuilder = DynamicModule.DefineType(name, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable);
469
470			AddInterfacesFromBaseType(type, typeBuilder);
471
472			typeBuilder.SetParent(type);
473			var interfaceType = typeof(INotifyPropertyChanged);
474			typeBuilder.AddInterfaceImplementation(interfaceType);
475			return typeBuilder;
476		}
477
478		private static void AddInterfacesFromBaseType(Type type, TypeBuilder typeBuilder)
479		{
480			var interfaces = type.GetInterfaces();
481			foreach (var interfaceType in interfaces)
482			{
483				typeBuilder.AddInterfaceImplementation(interfaceType);
484			}
485		}
486
487		private static string CreateUniqueName(string prefix)
488		{
489			var uid = Guid.NewGuid().ToString();
490			uid = uid.Replace('-', '_');
491			var name = string.Format("{0}{1}", prefix, uid);
492			return name;
493		}
494	}
495}
496#endif