protected EmittedMember(EmittedClass type, string name) { Contracts.Require.IsNotEmpty("name", name); this.TargetClass = type; this.Name = name; }
public EmittedProperty(EmittedClass type, string name, TypeRef propertyType, bool isStatic) : base(type, name) { Contracts.Require.IsNotNull("propertyType", propertyType); this.PropertyType = propertyType; this._isStatic = isStatic; }
public EmittedField(EmittedClass type, string name, TypeRef fieldType) : base(type, name) { Contracts.Require.IsNotNull("type", type); Contracts.Require.IsNotNull("name", name); this.FieldType = fieldType; this.Attributes = FieldAttributes.Private; }
static void ImplementIDataTransferObject(EmittedClass builder, EmittedConstructor cctor, List <PropertyInfo> props, EmittedField dirtyFlags) { builder.AddInterfaceImplementation(typeof(IDataTransferObject)); ImplementIDataTransferObjectGetDirtyFlags(builder, dirtyFlags); ImplementIDataTransferObjectResetDirtyFlags(builder, props, dirtyFlags); ImplementIDataTransferObjectIsDirty(builder, cctor, props, dirtyFlags); ImplementICloneableClone(builder, props, dirtyFlags); }
static void ImplementPropertiesForInterface(Type intf, EmittedClass builder, List <PropertyInfo> props, EmittedField dirtyFlags, EmittedMethod propChanged) { var properties = intf.GetProperties(); foreach (var p in properties) { ImplementPropertyFor(intf, builder, props, p, dirtyFlags, propChanged); props.Add(p); } }
static void ImplementIDataTransferObjectResetDirtyFlags(EmittedClass builder, List <PropertyInfo> props, EmittedField dirtyFlags) { var method = builder.DefineMethod("ResetDirtyFlags"); method.ClearAttributes(); method.IncludeAttributes(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final); method.ContributeInstructions( (m, il) => { il.Nop(); il.LoadArg_0(); il.LoadValue(props.Count); il.New <BitVector>(typeof(int)); il.StoreField(dirtyFlags); il.Nop(); }); }
static void ImplementIDataTransferObjectGetDirtyFlags(EmittedClass builder, EmittedField dirtyFlags) { var method = builder.DefineMethod("GetDirtyFlags"); method.ClearAttributes(); method.IncludeAttributes(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final); method.ReturnType = TypeRef.FromType <BitVector>(); method.ContributeInstructions( (m, il) => { il.DeclareLocal(typeof(BitVector)); il.Nop(); il.LoadArg_0(); il.LoadFieldAddress(dirtyFlags); il.Call <BitVector>("Clone"); il.UnboxAny(typeof(BitVector)); il.StoreLocal_0(); var exit = il.DefineLabel(); il.Branch_ShortForm(exit); il.MarkLabel(exit); il.LoadLocal_0(); }); }
static void ImplementPropertyFor(Type intf, EmittedClass builder, List <PropertyInfo> props, PropertyInfo property, EmittedField dirtyFlags, EmittedMethod propChanged) { var fieldName = String.Concat("<", intf.Name, "_", property.Name, ">_field"); var prop = builder.DefinePropertyFromPropertyInfo(property); EmittedField field = null; var fieldType = property.PropertyType; Type observableCollection = null; Type genericArgType = null; if (fieldType.IsInterface && fieldType.IsGenericType) { var genericDef = fieldType.GetGenericTypeDefinition(); if (genericDef == typeof(IList <>) || genericDef == typeof(ICollection <>)) { genericArgType = fieldType.GetGenericArguments()[0]; observableCollection = typeof(ObservableCollection <>).MakeGenericType(genericArgType); field = builder.DefineField(fieldName, observableCollection); } } if (field == null) { field = builder.DefineField(fieldName, property.PropertyType); } prop.BindField(field); var captureDirtyFlagsIndex = props.Count; prop.AddGetter() .ContributeInstructions((m, il) => { il.LoadArg_0(); il.LoadField(field); }); if (property.CanWrite) { prop.AddSetter() .ContributeInstructions((m, il) => { var exit = il.DefineLabel(); il.DeclareLocal(typeof(bool)); il.Nop(); if (fieldType.IsArray) { var elmType = fieldType.GetElementType(); LoadFieldFromThisAndValue(il, field); il.Call(typeof(Extensions).GetMethod("EqualsOrItemsEqual", BindingFlags.Static | BindingFlags.Public) .MakeGenericMethod(elmType)); } else if (fieldType.IsClass) { var opEquality = fieldType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.Static); if (opEquality != null) { LoadFieldFromThisAndValue(il, field); il.Call(opEquality); } else { il.Call(typeof(EqualityComparer <>).MakeGenericType(fieldType) .GetMethod("get_Default", BindingFlags.Static | BindingFlags.Public)); LoadFieldFromThisAndValue(il, field); il.CallVirtual(typeof(IEqualityComparer <>).MakeGenericType(fieldType) .GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance, null, new[] { fieldType, fieldType }, null )); } } else { LoadFieldFromThisAndValue(il, field); il.CompareEquality(fieldType); } il.StoreLocal_0(); il.LoadLocal_0(); il.BranchIfTrue_ShortForm(exit); il.Nop(); il.LoadArg_0(); il.LoadArg_1(); il.StoreField(field); il.LoadArg_0(); il.LoadFieldAddress(dirtyFlags); il.LoadValue(captureDirtyFlagsIndex); il.LoadValue(true); il.Call <BitVector>("set_Item"); il.Nop(); il.LoadArg_0(); il.LoadValue(prop.Name); il.Call(propChanged); il.Nop(); il.Nop(); il.MarkLabel(exit); }); } else if (observableCollection != null) { var observer = builder.DefineMethod(String.Concat("<", intf.Name, "_", property.Name, ">_field_CollectionChanged")); observer.ClearAttributes(); observer.IncludeAttributes(MethodAttributes.Private | MethodAttributes.HideBySig); observer.DefineParameter("sender", typeof(object)); observer.DefineParameter("e", typeof(NotifyCollectionChangedEventArgs)); observer.ContributeInstructions( (m, il) => { il.Nop(); il.LoadArg_0(); il.LoadFieldAddress(dirtyFlags); il.LoadValue(captureDirtyFlagsIndex); il.LoadValue(true); il.Call <BitVector>("set_Item"); il.Nop(); il.LoadArg_0(); il.LoadValue(property.Name); il.Call(propChanged); il.Nop(); }); var setter = prop.AddSetter(); setter.ExcludeAttributes(MethodAttributes.Public); setter.IncludeAttributes(MethodAttributes.Private); setter.ContributeInstructions((m, il) => { var isnull = il.DefineLabel(); var after = il.DefineLabel(); il.DeclareLocal <bool>(); il.Nop(); il.LoadArg_1(); il.LoadNull(); il.CompareEqual(); il.StoreLocal_0(); il.LoadLocal_0(); il.BranchIfTrue_ShortForm(isnull); il.Nop(); il.LoadArg_0(); il.LoadArg_1(); il.NewObj(observableCollection.GetConstructor(new[] { typeof(IEnumerable <>).MakeGenericType(genericArgType) })); il.StoreField(field); il.Nop(); il.Branch_ShortForm(after); il.MarkLabel(isnull); il.Nop(); il.LoadArg_0(); il.NewObj(observableCollection.GetConstructor(Type.EmptyTypes)); il.StoreField(field); il.Nop(); il.MarkLabel(after); il.LoadArg_0(); il.LoadField(field); il.LoadArg_0(); il.Emit(OpCodes.Ldftn, observer.Builder); // This seems really brittle... il.NewObj(typeof(NotifyCollectionChangedEventHandler).GetConstructor(new[] { typeof(object), typeof(IntPtr) })); il.CallVirtual(observableCollection.GetEvent("CollectionChanged") .GetAddMethod()); il.Nop(); }); } }
static EmittedMethod ImplementINotifyPropertyChanged(EmittedClass builder) { var evtType = typeof(PropertyChangedEventHandler); builder.AddInterfaceImplementation(typeof(INotifyPropertyChanged)); var propertyChanged = builder.Builder.DefineEvent("PropertyChanged", EventAttributes.None, evtType); var propertyChangedBackingField = builder.DefineField <PropertyChangedEventHandler>("<PropertyChanged>"); propertyChangedBackingField.ClearAttributes(); propertyChangedBackingField.IncludeAttributes(FieldAttributes.Private); var ctor = typeof(NonSerializedAttribute).GetConstructor(Type.EmptyTypes); Debug.Assert(ctor != null, "ctor != null"); propertyChangedBackingField.Builder.SetCustomAttribute(new CustomAttributeBuilder(ctor, new object[0])); // Emit a standard add <event handler> method (similar to what the C# compiler does)... /* * public void add_PropertyChanged(PropertyChangedEventHandler value) * { * PropertyChangedEventHandler orig; * PropertyChangedEventHandler propertyChanged = this.PropertyChanged; * do * { * orig = propertyChanged; * PropertyChangedEventHandler updated = (PropertyChangedEventHandler) Delegate.Combine(orig, value); * check = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this._propertyChanged, updated, orig); * } * while (check != orig); * } */ var add = builder.DefineMethod("add_PropertyChanged"); add.ClearAttributes(); add.IncludeAttributes(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final); add.DefineParameter("value", evtType); add.ContributeInstructions( (m, il) => { var retry = il.DefineLabel(); il.DeclareLocal(evtType); il.DeclareLocal(evtType); il.DeclareLocal(evtType); il.DeclareLocal(typeof(bool)); il.LoadArg_0(); il.LoadField(propertyChangedBackingField); il.StoreLocal_0(); il.MarkLabel(retry); il.LoadLocal_0(); il.StoreLocal_1(); il.LoadLocal_1(); il.LoadArg_1(); il.Call <Delegate>("Combine", BindingFlags.Static | BindingFlags.Public, typeof(Delegate), typeof(Delegate)); il.CastClass <PropertyChangedEventHandler>(); il.StoreLocal_2(); il.LoadArg_0(); il.LoadFieldAddress(propertyChangedBackingField); il.LoadLocal_2(); il.LoadLocal_1(); var compex = (from c in typeof(Interlocked).GetMethods(BindingFlags.Static | BindingFlags.Public) where c.IsGenericMethodDefinition && c.Name == "CompareExchange" select c).Single(); il.Call(compex.MakeGenericMethod(evtType)); il.StoreLocal_0(); il.LoadLocal_0(); il.LoadLocal_1(); il.CompareEqual(); il.StoreLocal_3(); il.LoadLocal_3(); il.BranchIfTrue_ShortForm(retry); }); var remove = builder.DefineMethod("remove_PropertyChanged"); remove.ClearAttributes(); remove.IncludeAttributes(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final); remove.DefineParameter("value", evtType); remove.ContributeInstructions( (m, il) => { var retry = il.DefineLabel(); il.DeclareLocal(evtType); il.DeclareLocal(evtType); il.DeclareLocal(evtType); il.DeclareLocal(typeof(bool)); il.LoadArg_0(); il.LoadField(propertyChangedBackingField); il.StoreLocal_0(); il.MarkLabel(retry); il.LoadLocal_0(); il.StoreLocal_1(); il.LoadLocal_1(); il.LoadArg_1(); il.Call <Delegate>("Remove", BindingFlags.Static | BindingFlags.Public, typeof(Delegate), typeof(Delegate)); il.CastClass <PropertyChangedEventHandler>(); il.StoreLocal_2(); il.LoadArg_0(); il.LoadFieldAddress(propertyChangedBackingField); il.LoadLocal_2(); il.LoadLocal_1(); var compex = (from c in typeof(Interlocked).GetMethods(BindingFlags.Static | BindingFlags.Public) where c.IsGenericMethodDefinition && c.Name == "CompareExchange" select c).Single(); il.Call(compex.MakeGenericMethod(evtType)); il.StoreLocal_0(); il.LoadLocal_0(); il.LoadLocal_1(); il.CompareEqual(); il.StoreLocal_3(); il.LoadLocal_3(); il.BranchIfTrue_ShortForm(retry); }); propertyChanged.SetAddOnMethod(add.Builder); propertyChanged.SetRemoveOnMethod(remove.Builder); var onPropertyChanged = builder.DefineMethod("HandlePropertyChanged"); onPropertyChanged.ClearAttributes(); onPropertyChanged.IncludeAttributes(MethodAttributes.HideBySig); onPropertyChanged.DefineParameter("propName", typeof(String)); onPropertyChanged.ContributeInstructions( (m, il) => { var exit = il.DefineLabel(); il.DeclareLocal(typeof(bool)); il.Nop(); il.LoadArg_0(); il.LoadField(propertyChangedBackingField); il.LoadNull(); il.CompareEqual(); il.StoreLocal_0(); il.LoadLocal_0(); il.BranchIfTrue_ShortForm(exit); il.Nop(); il.LoadArg_0(); il.LoadField(propertyChangedBackingField); il.LoadArg_0(); il.LoadArg_1(); il.New <PropertyChangedEventArgs>(typeof(string)); il.CallVirtual <PropertyChangedEventHandler>("Invoke", typeof(object), typeof(PropertyChangedEventArgs)); il.Nop(); il.Nop(); il.MarkLabel(exit); }); return(onPropertyChanged); }
static void ImplementIDataTransferObjectIsDirty(EmittedClass builder, EmittedConstructor cctor, List <PropertyInfo> props, EmittedField dirtyFlags) { var fieldMap = builder.DefineField <string[]>("__fieldMap"); fieldMap.ClearAttributes(); fieldMap.IncludeAttributes(FieldAttributes.Static | FieldAttributes.InitOnly | FieldAttributes.Private); cctor.ContributeInstructions((m, il) => { var arr = il.DeclareLocal(typeof(String[])); il.Nop(); il.NewArr(typeof(string), props.Count); il.StoreLocal(arr); for (var i = 0; i < props.Count; i++) { il.LoadLocal(arr); il.LoadValue(i); il.LoadValue(props[i].Name); il.Emit(OpCodes.Stelem, typeof(string)); } il.LoadLocal(arr); il.StoreField(fieldMap); il.Nop(); il.Nop(); }); var method = builder.DefineMethod("IsDirty"); method.ClearAttributes(); method.IncludeAttributes(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final); method.ReturnType = TypeRef.FromType <bool>(); method.DefineParameter("member", typeof(String)); method.ContributeInstructions( (m, il) => { il.DeclareLocal(typeof(Int32)); il.DeclareLocal(typeof(bool)); il.DeclareLocal(typeof(bool)); var proceed = il.DefineLabel(); var yep = il.DefineLabel(); il.Nop(); il.LoadArg_1(); il.LoadNull(); il.CompareEqual(); il.LoadValue(false); il.CompareEqual(); il.StoreLocal_2(); il.LoadLocal_2(); il.BranchIfTrue_ShortForm(proceed); il.LoadValue("member"); il.New <ArgumentNullException>(typeof(string)); il.Throw(); il.MarkLabel(proceed); il.LoadField(fieldMap); il.LoadArg_1(); var indexOf = typeof(Array).MatchGenericMethod("IndexOf", BindingFlags.Public | BindingFlags.Static, 1, typeof(int), typeof(string[]), typeof(string)); il.Call(indexOf.MakeGenericMethod(typeof(string))); il.StoreLocal_0(); il.LoadLocal_0(); il.LoadValue(0); il.CompareLessThan(); il.LoadValue(0); il.CompareEqual(); il.StoreLocal_2(); il.LoadLocal_2(); il.BranchIfTrue(yep); il.Nop(); il.LoadValue("member"); il.LoadValue(String.Concat(typeof(T).GetReadableSimpleName(), " does not define property: `")); il.LoadArg_1(); il.LoadValue("`."); il.Call <string>("Concat", BindingFlags.Static | BindingFlags.Public, typeof(string), typeof(string), typeof(string)); il.NewObj( typeof(ArgumentOutOfRangeException).GetConstructor(new[] { typeof(string), typeof(string) })); il.Throw(); il.MarkLabel(yep); il.LoadArg_0(); il.LoadFieldAddress(dirtyFlags); il.LoadLocal_0(); il.Call <BitVector>("get_Item", typeof(int)); il.StoreLocal_1(); il.DefineAndMarkLabel(); il.LoadLocal_1(); }); }
static void ImplementICloneableClone(EmittedClass builder, List <PropertyInfo> props, EmittedField dirtyFlags) { var method = builder.DefineMethod("Clone"); method.ClearAttributes(); method.IncludeAttributes(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final); method.ReturnType = TypeRef.FromType <object>(); method.ContributeInstructions( (m, il) => { var res = il.DeclareLocal(builder.Builder); il.DeclareLocal(typeof(object)); var flag = il.DeclareLocal(typeof(bool)); il.Nop(); il.LoadArg_0(); il.Call <Object>("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic); il.CastClass(builder.Builder); il.StoreLocal_0(); il.LoadLocal_0(); il.LoadArg_0(); il.LoadFieldAddress(dirtyFlags); il.Call <BitVector>("Copy"); il.StoreField(dirtyFlags); il.LoadLocal_0(); il.LoadNull(); il.StoreField(builder.Fields.Single(f => f.Name == "<PropertyChanged>") .Builder); foreach (var prop in props) { var fieldType = prop.PropertyType; if (fieldType.IsInterface && fieldType.IsGenericType) { var genericDef = fieldType.GetGenericTypeDefinition(); if (genericDef == typeof(IList <>) || genericDef == typeof(ICollection <>)) { EmittedProperty ep; if (builder.TryGetProperty(prop.Name, out ep)) { il.Nop(); il.LoadLocal_0(); il.LoadArg_0(); il.LoadField(ep.BoundField); il.Call(ep.Setter.Builder); il.Nop(); } } } else if (fieldType.IsArray) { // copy the first rank EmittedProperty ep; if (builder.TryGetProperty(prop.Name, out ep)) { var after = il.DefineLabel(); var len = il.DeclareLocal(typeof(int)); il.LoadArg_0(); il.LoadField(ep.BoundField); il.LoadNull(); il.CompareEqual(); il.StoreLocal(flag); il.LoadLocal(flag); il.BranchIfTrue(after); il.Nop(); il.LoadArg_0(); il.LoadField(ep.BoundField); il.Emit(OpCodes.Ldlen); il.ConvertToInt32(); il.StoreLocal(len); il.LoadLocal(res); il.LoadLocal(len); il.Emit(OpCodes.Newarr, fieldType.GetElementType()); il.StoreField(ep.BoundField); il.LoadArg_0(); il.LoadField(ep.BoundField); il.LoadLocal(res); il.LoadField(ep.BoundField); il.LoadLocal(len); il.Call <Array>("Copy", BindingFlags.Static | BindingFlags.Public, typeof(Array), typeof(Array), typeof(int)); il.Nop(); il.Nop(); il.MarkLabel(after); } } } il.LoadLocal_0(); il.StoreLocal_1(); var exit = il.DefineLabel(); il.Branch_ShortForm(exit); il.MarkLabel(exit); il.LoadLocal_1(); }); }
public EmittedClass DefineClass(string className, TypeAttributes attributes , Type supertype, Type[] interfaces) { Contracts.Require.IsNotNull("className", className); CheckClassName(className); EmittedClass cls = new EmittedClass(_module, className, attributes, supertype, interfaces); _classes.Add(className, cls); return cls; }
public EmittedClass DefineClass(string className) { Contracts.Require.IsNotNull("className", className); CheckClassName(className); EmittedClass cls = new EmittedClass(_module, className); _classes.Add(className, cls); return cls; }
public EmittedMethod(EmittedClass type, string name) : base(type, name) { this.CallingConvention = CallingConventions.Standard | CallingConventions.HasThis; }
public EmittedMethodBase(EmittedClass type, string name) : base(type, name) { _parameters = new List<EmittedParameter>(); _locals = new List<EmittedLocal>(); }
public EmittedConstructor(EmittedClass type, string name) : base(type, name) { this.IncludeAttributes(MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public); this.CallingConvention = CallingConventions.Standard; }