/// <summary> /// Create a singleton field used to store property information for the provided property. /// </summary> /// <param name="property">The property weaver.</param> /// <returns></returns> public Variable CreatePropertyInfo(PropertyEmitter property) { var parent = property.Parent.Target.IsNotPublic ? property.Parent : CreateTypeContainer(property.Parent.Target); var type = property.Parent.Target; var sta = (property.Target.GetMethod ?? property.Target.SetMethod).IsStatic; var name = $"<{property.Target.Name}>k__PropertyInfo"; var existing = parent.GetField(name, Context.Finder.PropertyInfo, toStatic: true); if (existing != null) { return(existing); } var field = parent.EmitField(name, Context.Finder.PropertyInfo, toStatic: true, toPublic: true); var flags = BindingFlags.NonPublic | BindingFlags.Public | (sta ? BindingFlags.Static : BindingFlags.Instance); var il = parent.GetStaticConstructor().GetIL(); il.Emit(Codes.Nop); il.Emit(Codes.LoadToken(type.GetGeneric())); il.Emit(Codes.InvokeStatic(Context.Finder.TypeGetTypeFromHandle)); il.Emit(Codes.String(property.Target.Name)); il.Emit(Codes.Int((int)flags)); il.Emit(Codes.Invoke(Context.Finder.TypeGetProperty)); il.Emit(Codes.Store(field)); return(field); }
void EventEmit(IViewEvent viewEvent, List <MemberEmitter> ret) { string name = viewEvent.Name.Replace("/", "").Replace(".", ""); string genericType = (viewEvent.EventType() != null) ? $"<{GetTypeString(viewEvent.EventType())}>" : ""; PropertyEmitter property = new PropertyEmitter(); property.Name = "On" + name; property.Type = "event Action" + genericType; property.Summary = $"BindingPath : {viewEvent.Name}\nSender: {viewEvent.ToString()}"; property.Getter = new DelegateEmitter(w => { w.WriteLine("add"); using (w.Bracket()) { w.WriteLine($"m_Event.Subscribe{genericType}(\"{viewEvent.Name}\", value);"); } }); property.Setter = new DelegateEmitter(w => { w.WriteLine("remove"); using (w.Bracket()) { w.WriteLine($"m_Event.Unsubscribe{genericType}(\"{viewEvent.Name}\", value);"); } }); ret.Add(property); }
/// <summary> /// Weaves an implementation of a property against the provided type. /// </summary> /// <param name="emitter">The emitter.</param> /// <param name="field">The attribute field.</param> /// <param name="property">The property.</param> /// <param name="interfaceType">The type of the interface.</param> public void WeaveImplementedProperty(TypeEmitter emitter, Variable field, PropertyDefinition property, TypeDefinition interfaceType) { var emitted = emitter.EmitProperty(property.Name, property.PropertyType.Import(), toBackingField: true); var implemented = field.Type.GetProperty(property.Name, property.PropertyType)?.Resolve(); if (implemented == null) { implemented = field.Type.GetProperty($"{interfaceType.FullName}.{property.Name}", returnType: property.PropertyType)?.Resolve(); if (implemented == null) { throw new MissingMemberException($"Cannot implement '{field.Type.FullName}' as it does not implement property '{property.Name}'"); } } var source = new PropertyEmitter(emitter, implemented); if (source.HasGetter && !emitted.HasGetter) { var getter = emitted.GetGetter(); var il = getter.GetIL(); var propertyGet = property.GetMethod?.Import() ?? implemented.GetMethod.Import(); getter.Body.SimplifyMacros(); il.Emit(Codes.Nop); il.Emit(Codes.ThisIf(field)); il.Emit(Codes.Cast(interfaceType)); il.Emit(Codes.Load(field)); il.Emit(Codes.Invoke(propertyGet.GetGeneric())); il.Emit(Codes.Return); getter.Body.OptimizeMacros(); getter.Body.InitLocals = true; } if (source.HasSetter && !emitted.HasSetter) { var setter = emitted.GetSetter(); var il = setter.GetIL(); var propertySet = property.SetMethod?.Import() ?? implemented.SetMethod.Import(); setter.Body.SimplifyMacros(); il.Emit(Codes.Nop); il.Emit(Codes.ThisIf(field)); il.Emit(Codes.Load(field)); il.Emit(Codes.Arg(setter.Target.IsStatic ? 0 : 1)); il.Emit(Codes.Invoke(propertySet.GetGeneric())); il.Emit(Codes.Return); setter.Body.OptimizeMacros(); setter.Body.InitLocals = true; } }
/// <summary> /// Create an attribute variable for a property definition. /// </summary> /// <param name="property">The property.</param> /// <param name="get">The getter method.</param> /// <param name="set">The setter method.</param> /// <param name="attribute">The attribute.</param> /// <param name="field">The optional field reference which was routed.</param> /// <returns></returns> public Variable[] CreateAttribute(PropertyEmitter property, MethodEmitter get, MethodEmitter set, CustomAttribute attribute, MemberReference field) { var method = get ?? set; var sta = method.Target.IsStatic; var options = attribute.GetAttribute(Context.Finder.CompilationOptionsAttribute); var scope = options.GetProperty("Scope", notFound: AttributeScopeSingleton); if (sta) { if (scope == AttributeScopeInstanced) { scope = AttributeScopeSingleton; } else if (scope == AttributeScopeMultiInstanced) { scope = AttributeScopeMultiSingleton; } } var hasGet = attribute.HasInterface(Context.Finder.IPropertyGetInterceptor); var hasSet = attribute.HasInterface(Context.Finder.IPropertySetInterceptor); switch (scope) { case AttributeScopeAdhoc: var adhocGet = hasGet && get != null?CreateAttributeAdhoc(get, attribute, property.Target) : null; var adhocSet = hasSet && set != null?CreateAttributeAdhoc(set, attribute, property.Target) : null; return(new[] { adhocGet, adhocSet }); case AttributeScopeInstanced: var instanced = CreateAttributeInstanced(property.Parent, attribute, field ?? property.Target); return(new[] { hasGet?instanced : null, hasSet ? instanced : null }); case AttributeScopeMultiInstanced: var multi = CreateAttributeMultiInstanced(property.Parent, attribute, field ?? property.Target); return(new[] { hasGet?multi : null, hasSet ? multi : null }); case AttributeScopeSingleton: var singleton = CreateAttributeSingleton(property.Parent, attribute, field ?? property.Target); return(new[] { hasGet?singleton : null, hasSet ? singleton : null }); case AttributeScopeMultiSingleton: var multiSingleton = CreateAttributeMultiSingleton(property.Parent, attribute, field ?? property.Target); return(new[] { hasGet?multiSingleton : null, hasSet ? multiSingleton : null }); default: throw new NotSupportedException($"Cannot create attribute '{attribute.AttributeType.FullName}' with scope '{scope}'"); } }
public void BuildPropertyEmitter(ClassEmitter classEmitter) { if (emitter != null) { throw new InvalidOperationException("Emitter is already created. It is illegal to invoke this method twice."); } emitter = classEmitter.CreateProperty(name, attributes, type, arguments); foreach (var attribute in customAttributes) { emitter.DefineCustomAttribute(attribute); } }
void PropertyEmit(IBindable bindable, List <MemberEmitter> ret) { PropertyEmitter property = new PropertyEmitter(); string name = bindable.Path.Replace("/", "").Replace(".", ""); if (bindable is IViewEvent) { name += m_Config.EventValueSuffix; } string type = GetTypeString(bindable.BindType()); property.Name = name; property.Type = type; property.Setter = new WriteLineEmitter($"set {{ SetImpl<{type}>(\"{bindable.Path}\", value); }}"); property.Getter = new WriteLineEmitter($"get {{ return GetImpl<{type}>(\"{bindable.Path}\"); }}"); property.Summary = $"BindingPath : {bindable.Path}\nTarget: {bindable.ToString()}"; ret.Add(property); }
public static PropertyDefinition ChangeToProperty(this FieldDefinition field) { var emitter = new PropertyEmitter(field.Name, field.FieldType, field.DeclaringType, getterAttributes: MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.SpecialName, setterAttributes: MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.SpecialName ); field.Name = field.GetBackingName(); field.IsPublic = false; field.IsPrivate = true; field.CustomAttributes.Add(new CustomAttribute( field.DeclaringType.Module.ImportReference( typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute) .GetConstructors() .Single() ) )); return(emitter.Emit()); }
void CommandEmit(IViewEvent viewEvent, List <MemberEmitter> ret) { string name = viewEvent.Name.Replace("/", "").Replace(".", ""); string genericType = (viewEvent.EventType() != null) ? $"<{GetTypeString(viewEvent.EventType())}>" : ""; FieldEmitter field = new FieldEmitter(); field.Accessibility = "private"; field.Name = "m_" + name + m_Config.CommandSuffix; field.Type = "BindingCommand" + genericType; ret.Add(field); PropertyEmitter property = new PropertyEmitter(); property.Name = name + m_Config.CommandSuffix; property.Type = "ICommand" + genericType; property.Summary = $"BindingPath : {viewEvent.Name}\nSender: {viewEvent.ToString()}"; property.Getter = new DelegateEmitter(w => { w.WriteLine("get"); using (w.Bracket()) { w.WriteLine($"return m_{name}{m_Config.CommandSuffix}?.Get() ?? null;"); } }); property.Setter = new DelegateEmitter(w => { w.WriteLine("set"); using (w.Bracket()) { w.WriteLine($"if (m_{name}{m_Config.CommandSuffix} == null) m_{name}{m_Config.CommandSuffix} = new BindingCommand{genericType}(\"{viewEvent.Name}\", this);"); w.WriteLine($"m_{name}{m_Config.CommandSuffix}.Set(value);"); } }); ret.Add(property); }
private static Type CreateProxyType(Type interfaceType) { if (!interfaceType.IsInterface) { throw new ArgumentException("Only interfaces can be proxied", "interfaceType"); } string name = string.Format("Proxy<{0}>", Regex.Replace(interfaceType.AssemblyQualifiedName ?? interfaceType.FullName ?? interfaceType.Name, @"[\s,]+", "_")); List<Type> allInterfaces = new List<Type> { interfaceType }; allInterfaces.AddRange(interfaceType.GetInterfaces()); Debug.WriteLine(name, "Emitting proxy type"); TypeBuilder typeBuilder = proxyModule.DefineType(name, TypeAttributes.Class|TypeAttributes.Sealed|TypeAttributes.Public, typeof(ProxyBase), allInterfaces.ToArray()); ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); ILGenerator ctorIl = constructorBuilder.GetILGenerator(); ctorIl.Emit(OpCodes.Ldarg_0); ctorIl.Emit(OpCodes.Call, proxyBase_ctor); ctorIl.Emit(OpCodes.Ret); FieldBuilder propertyChangedField = null; if (typeof(INotifyPropertyChanged).IsAssignableFrom(interfaceType)) { propertyChangedField = typeBuilder.DefineField("PropertyChanged", typeof(PropertyChangedEventHandler), FieldAttributes.Private); MethodBuilder addPropertyChangedMethod = typeBuilder.DefineMethod("add_PropertyChanged", MethodAttributes.Public|MethodAttributes.HideBySig|MethodAttributes.SpecialName|MethodAttributes.NewSlot|MethodAttributes.Virtual, typeof(void), new[] {typeof(PropertyChangedEventHandler)}); ILGenerator addIl = addPropertyChangedMethod.GetILGenerator(); addIl.Emit(OpCodes.Ldarg_0); addIl.Emit(OpCodes.Dup); addIl.Emit(OpCodes.Ldfld, propertyChangedField); addIl.Emit(OpCodes.Ldarg_1); addIl.Emit(OpCodes.Call, delegate_Combine); addIl.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler)); addIl.Emit(OpCodes.Stfld, propertyChangedField); addIl.Emit(OpCodes.Ret); MethodBuilder removePropertyChangedMethod = typeBuilder.DefineMethod("remove_PropertyChanged", MethodAttributes.Public|MethodAttributes.HideBySig|MethodAttributes.SpecialName|MethodAttributes.NewSlot|MethodAttributes.Virtual, typeof(void), new[] {typeof(PropertyChangedEventHandler)}); ILGenerator removeIl = removePropertyChangedMethod.GetILGenerator(); removeIl.Emit(OpCodes.Ldarg_0); removeIl.Emit(OpCodes.Dup); removeIl.Emit(OpCodes.Ldfld, propertyChangedField); removeIl.Emit(OpCodes.Ldarg_1); removeIl.Emit(OpCodes.Call, delegate_Remove); removeIl.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler)); removeIl.Emit(OpCodes.Stfld, propertyChangedField); removeIl.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(addPropertyChangedMethod, iNotifyPropertyChanged_PropertyChanged.GetAddMethod()); typeBuilder.DefineMethodOverride(removePropertyChangedMethod, iNotifyPropertyChanged_PropertyChanged.GetRemoveMethod()); } List<PropertyInfo> propertiesToImplement = new List<PropertyInfo>(); // first we collect all properties, those with setters before getters in order to enable less specific redundant getters foreach (PropertyInfo property in allInterfaces.Where(intf => intf != typeof(INotifyPropertyChanged)).SelectMany(intf => intf.GetProperties())) { if (property.CanWrite) { propertiesToImplement.Insert(0, property); } else { propertiesToImplement.Add(property); } } Dictionary<string, PropertyEmitter> fieldBuilders = new Dictionary<string, PropertyEmitter>(); foreach (PropertyInfo property in propertiesToImplement) { PropertyEmitter propertyEmitter; if (fieldBuilders.TryGetValue(property.Name, out propertyEmitter)) { if ((propertyEmitter.PropertyType != property.PropertyType) && ((property.CanWrite) || (!property.PropertyType.IsAssignableFrom(propertyEmitter.PropertyType)))) { throw new ArgumentException(string.Format("The interface has a conflicting property {0}", property.Name), "interfaceType"); } } else { fieldBuilders.Add(property.Name, propertyEmitter = new PropertyEmitter(typeBuilder, property.Name, property.PropertyType, propertyChangedField)); } if (property.CanRead) { typeBuilder.DefineMethodOverride(propertyEmitter.GetGetter(property.PropertyType), property.GetGetMethod()); } if (property.CanWrite) { typeBuilder.DefineMethodOverride(propertyEmitter.GetSetter(property.PropertyType), property.GetSetMethod()); } } return typeBuilder.CreateType(); }
/// <summary> /// The method to be called to create the property level attributes for the PropertyEmitter /// </summary> /// <param name="emitter">The strongly typed emitter</param> /// <param name="propertyDecl">The type declaration to add the attribues to.</param> /// <param name="additionalAttributes">Additional attributes to emit</param> public void EmitPropertyAttributes(PropertyEmitter emitter, CodeMemberProperty propertyDecl, List<CodeAttributeDeclaration> additionalAttributes) { if (MetadataUtil.IsPrimitiveType(emitter.Item.TypeUsage.EdmType) || MetadataUtil.IsEnumerationType(emitter.Item.TypeUsage.EdmType)) { CodeAttributeDeclaration scalarPropertyAttribute = EmitSimpleAttribute(FQAdoFrameworkDataClassesName("EdmScalarPropertyAttribute")); if (emitter.IsKeyProperty) { Debug.Assert(emitter.Item.Nullable == false, "An EntityKeyProperty cannot be nullable."); AttributeEmitter.AddNamedAttributeArguments(scalarPropertyAttribute, "EntityKeyProperty", true); } if (!emitter.Item.Nullable) { AttributeEmitter.AddNamedAttributeArguments(scalarPropertyAttribute, "IsNullable", false); } propertyDecl.CustomAttributes.Add(scalarPropertyAttribute); } else //Complex property { Debug.Assert(MetadataUtil.IsComplexType(emitter.Item.TypeUsage.EdmType) || (MetadataUtil.IsCollectionType(emitter.Item.TypeUsage.EdmType)), "not a complex type or a collection type"); CodeAttributeDeclaration attribute = EmitSimpleAttribute(FQAdoFrameworkDataClassesName("EdmComplexPropertyAttribute")); propertyDecl.CustomAttributes.Add(attribute); // Have CodeDOM serialization set the properties on the ComplexObject, not the ComplexObject instance. attribute = EmitSimpleAttribute("System.ComponentModel.DesignerSerializationVisibility"); AttributeEmitter.AddAttributeArguments(attribute, new object[] { new CodePropertyReferenceExpression( new CodeTypeReferenceExpression(TypeReference.ForType( typeof(System.ComponentModel.DesignerSerializationVisibility))),"Content") }); propertyDecl.CustomAttributes.Add(attribute); if (!MetadataUtil.IsCollectionType(emitter.Item.TypeUsage.EdmType)) { // Non-collection complex properties also need additional serialization attributes to force them to be explicitly serialized if they are null // If this is omitted, null complex properties do not get explicitly set to null during deserialization, which causes // them to be lazily constructed once the property is accessed after the entity is deserialized. If the property is // actually null during serialiation, that means the user has explicitly set it, so we need to maintain that during serialization. // This doesn't apply to collection types because they aren't lazily constructed and don't need this extra information. attribute = EmitSimpleAttribute("System.Xml.Serialization.XmlElement"); AttributeEmitter.AddNamedAttributeArguments(attribute, "IsNullable", true); propertyDecl.CustomAttributes.Add(attribute); attribute = EmitSimpleAttribute("System.Xml.Serialization.SoapElement"); AttributeEmitter.AddNamedAttributeArguments(attribute, "IsNullable", true); propertyDecl.CustomAttributes.Add(attribute); } } // serialization attribute AddDataMemberAttribute(propertyDecl); if (additionalAttributes != null && additionalAttributes.Count > 0) { try { propertyDecl.CustomAttributes.AddRange(additionalAttributes.ToArray()); } catch (ArgumentNullException e) { emitter.Generator.AddError(Strings.InvalidAttributeSuppliedForProperty(emitter.Item.Name), ModelBuilderErrorCode.InvalidAttributeSuppliedForProperty, EdmSchemaErrorSeverity.Error, e); } } EmitGeneratedCodeAttribute(propertyDecl); }
/// <summary> /// The method to be called to create the property level attributes for the PropertyEmitter /// </summary> /// <param name="emitter">The strongly typed emitter</param> /// <param name="propertyDecl">The type declaration to add the attribues to.</param> /// <param name="additionalAttributes">Additional attributes to emit</param> public void EmitPropertyAttributes(PropertyEmitter emitter, CodeMemberProperty propertyDecl, List<CodeAttributeDeclaration> additionalAttributes) { if (additionalAttributes != null && additionalAttributes.Count > 0) { try { propertyDecl.CustomAttributes.AddRange(additionalAttributes.ToArray()); } catch (ArgumentNullException e) { emitter.Generator.AddError(Strings.InvalidAttributeSuppliedForProperty(emitter.Item.Name), ModelBuilderErrorCode.InvalidAttributeSuppliedForProperty, EdmSchemaErrorSeverity.Error, e); } } }
public Type EmitClass(IEnumerable <Type> interfaceTypes, Type baseType, IEnumerable <MethodInfo> methodsToOverride, IEnumerable <PropertyInfo> propertiesToOverride, IEnumerable <EventInfo> eventsToOverride, ConstructorInfo baseConstructor, IEnumerable <CustomAttributeBuilder> attributeBuilders) { // Apply default values for parameters if (baseType == null) { baseType = typeof(EmittedClassBase); } // Check limitations for this version if (baseType != typeof(EmittedClassBase)) { throw new NotImplementedException("The only supported baseType value is 'EmittedClassBase' in this version."); } if ((interfaceTypes == null) || (interfaceTypes.Count() != 1)) { throw new NotImplementedException( "Current implementation should be provided with exactly one single interface to implement."); } Type interfaceType = interfaceTypes.Single(); // Validate arguments if (!interfaceType.IsInterface) { throw new ArgumentException("interfaceTypes can contain 'interface' types only. " + interfaceType.FullName + " is not an interface."); } // Check if the component is initialized if ((_moduleBuilder == null) || (_assemblyBuilder == null)) { throw new InvalidOperationException("The DefaultClassEmitter component is not initialized properly."); } var uniqueTypeNumber = Interlocked.Increment(ref _typeNumber); var typeName = DynamicTypePrefix + interfaceType.Name + uniqueTypeNumber; var typeBuilder = _moduleBuilder.DefineType( typeName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, typeof(EmittedClassBase), new[] { interfaceType }); // Add custom attributes if (attributeBuilders != null) { foreach (var builder in attributeBuilders) { typeBuilder.SetCustomAttribute(builder); } } // Implement properties, events and methods foreach (var propertyInfo in interfaceType.GetProperties()) { PropertyEmitter.EmitProperty(typeBuilder, propertyInfo); } foreach (var eventInfo in interfaceType.GetEvents()) { EventEmitter.EmitEvent(typeBuilder, eventInfo); } foreach (var methodInfo in interfaceType.GetMethods()) { MethodBuilder methodBuilder = MethodEmitter.EmitMethod( typeBuilder, methodInfo.Name, methodInfo.GetParameters().Select(pi => pi.ParameterType).ToArray(), methodInfo.GetParameters().Select(pi => pi.IsOut).ToArray(), methodInfo.ReturnType, methodInfo.ReflectedType, InterfaceMethodAttributes); typeBuilder.DefineMethodOverride(methodBuilder, methodInfo); } var result = typeBuilder.CreateTypeInfo(); // if (SaveEmittedAssembly) // _assemblyBuilder.Save(DynamicAssemblyName + ".dll"); return(result); }
/// <summary> /// Emit static factory method which creates an instance of the class and initializes /// non-nullable properties (taken as arguments) /// </summary> /// <param name="typeDecl"></param> protected virtual void EmitFactoryMethod(CodeTypeDeclaration typeDecl) { // build list of non-nullable properties ReadOnlyMetadataCollection<EdmProperty> properties = GetProperties(); List<EdmProperty> parameters = new List<EdmProperty>(properties.Count); foreach (EdmProperty property in properties) { bool include = IncludeFieldInFactoryMethod(property); if (include) { parameters.Add(property); } } // if there are no parameters, we don't emit anything (1 is for the null element) // nor do we emit everything if this is the Ref propertied ctor and the parameter list is the same as the many parametered ctor if (parameters.Count < 1) { return; } CodeMemberMethod method = new CodeMemberMethod(); CodeTypeReference typeRef = TypeReference.FromString(Item.Name); UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(Generator.IsLanguageCaseSensitive); string instanceName = uniqueIdentifierService.AdjustIdentifier(Utils.CamelCase(Item.Name)); // public static Class CreateClass(...) method.Attributes = MemberAttributes.Static | MemberAttributes.Public; method.Name = "Create" + Item.Name; if (NavigationPropertyEmitter.IsNameAlreadyAMemberName(Item, method.Name, Generator.LanguageAppropriateStringComparer)) { Generator.AddError(Strings.GeneratedFactoryMethodNameConflict(method.Name, Item.Name), ModelBuilderErrorCode.GeneratedFactoryMethodNameConflict, EdmSchemaErrorSeverity.Error); } method.ReturnType = typeRef; AttributeEmitter.AddGeneratedCodeAttribute(method); // output method summary comments CommentEmitter.EmitSummaryComments(Strings.FactoryMethodSummaryComment(Item.Name), method.Comments); // Class class = new Class(); CodeVariableDeclarationStatement createNewInstance = new CodeVariableDeclarationStatement( typeRef, instanceName, new CodeObjectCreateExpression(typeRef)); method.Statements.Add(createNewInstance); CodeVariableReferenceExpression instanceRef = new CodeVariableReferenceExpression(instanceName); // iterate over the properties figuring out which need included in the factory method foreach (EdmProperty property in parameters) { // CreateClass( ... , propType propName ...) PropertyEmitter propertyEmitter = new PropertyEmitter(Generator, property, UsingStandardBaseClass); CodeTypeReference propertyTypeReference = propertyEmitter.PropertyType; String parameterName = uniqueIdentifierService.AdjustIdentifier(Utils.FixParameterName(propertyEmitter.PropertyName, "argument")); parameterName = Utils.SetSpecialCaseForFxCopOnPropertyName(parameterName); CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression( propertyTypeReference, parameterName); CodeArgumentReferenceExpression paramRef = new CodeArgumentReferenceExpression(paramDecl.Name); method.Parameters.Add(paramDecl); // add comment describing the parameter CommentEmitter.EmitParamComments(paramDecl, Strings.FactoryParamCommentGeneral(propertyEmitter.PropertyName), method.Comments); CodeExpression newPropertyValue; if (TypeSemantics.IsComplexType(propertyEmitter.Item.TypeUsage)) { List<CodeExpression> complexVerifyParameters = new List<CodeExpression>(); complexVerifyParameters.Add(paramRef); complexVerifyParameters.Add(new CodePrimitiveExpression(propertyEmitter.PropertyName)); // if (null == param) { throw new ArgumentNullException("PropertyName"); } method.Statements.Add( new CodeConditionStatement( EmitExpressionEqualsNull(paramRef), new CodeThrowExceptionStatement( new CodeObjectCreateExpression( TypeReference.ForType(typeof(ArgumentNullException)), new CodePrimitiveExpression(parameterName) ) ) ) ); newPropertyValue = paramRef; } else { newPropertyValue = paramRef; } // Scalar property: // Property = param; // Complex property: // Property = StructuralObject.VerifyComplexObjectIsNotNull(param, propertyName); method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(instanceRef, propertyEmitter.PropertyName), newPropertyValue)); } // return class; method.Statements.Add(new CodeMethodReturnStatement(instanceRef)); // actually add the method to the class typeDecl.Members.Add(method); }
/// <summary> /// /// </summary> /// <param name="typeDecl"></param> protected virtual void EmitProperties(CodeTypeDeclaration typeDecl) { foreach (EdmMember member in Item.Members) { EdmProperty property = (member as EdmProperty); if ((null != property) && (property.DeclaringType == Item)) { PropertyEmitter propertyEmitter = new PropertyEmitter(Generator, property, _usingStandardBaseClass); propertyEmitter.Emit(typeDecl); } } }
public void WithAutoGetterSetter() { var emiter = new PropertyEmitter(this); emiter.EmitAuto(); }
/// <summary> /// /// </summary> /// <param name="typeDecl"></param> protected virtual void EmitProperties(CodeTypeDeclaration typeDecl) { foreach (EdmProperty property in Item.GetDeclaredOnlyMembers<EdmProperty>()) { PropertyEmitter propertyEmitter = new PropertyEmitter(Generator, property, _usingStandardBaseClass); propertyEmitter.Emit(typeDecl); } }
public override void EmitProperty(PropertyInfo propertyInfo) { var emitter = new PropertyEmitter(TypeBuilder, ImplField); emitter.Emit(propertyInfo); }
/// <summary> /// Weaves the interception logic of a property. /// </summary> /// <param name="parent"></param> /// <param name="item"></param> public void WeavePropertyInterceptors(TypeEmitter parent, PropertyInterceptorInfo item) { var property = item.Property; var getter = property.GetMethod != null ? new MethodEmitter(parent, property.GetMethod) : null; var setter = property.SetMethod != null ? new MethodEmitter(parent, property.SetMethod) : null; var count = item.Interceptors.Length; var weaver = new PropertyEmitter(parent, property); if (count == 0) { return; } var gInterceptors = new Variable[count]; var sInterceptors = new Variable[count]; for (int i = 0; i < count; i++) { var variables = CreateAttribute(weaver, getter, setter, item.Interceptors[i], item.Field); gInterceptors[i] = variables[0]; sInterceptors[i] = variables[1]; } var hasGetter = gInterceptors.Any(i => i != null); var hasSetter = sInterceptors.Any(i => i != null); var type = property.PropertyType; var info = CreatePropertyInfo(weaver); var field = property.GetBackingField(); var backing = (Variable)null; if (field != null) { var def = field.Resolve(); def.Attributes &= ~Mono.Cecil.FieldAttributes.InitOnly; backing = new Variable(def); } if (getter != null && hasGetter) { var il = getter.GetIL(); var result = getter.EmitLocal(property.PropertyType); il.Body.SimplifyMacros(); il.Position = il.GetFirst(); il.Insert = CodeInsertion.Before; if (backing != null) { il.Emit(Codes.ThisIf(backing)); il.Emit(Codes.Load(backing)); il.Emit(Codes.Store(result)); } else { if (type.IsValueType) { il.Emit(Codes.Address(result)); il.Emit(Codes.Init(type)); } else { il.Emit(Codes.Null); il.Emit(Codes.Store(result)); } } il.Try(); var leave = WeaveMethodReturnsRoute(getter, result, true); var cancel = il.EmitLabel(); var args = il.EmitLocal(Context.Finder.PropertyInterceptionArgs); il.Emit(getter.Target.IsStatic ? Codes.Null : Codes.This); il.Emit(Codes.Load(info)); il.Emit(Codes.Load(result)); il.Emit(Codes.Box(type)); il.Emit(Codes.Create(Context.Finder.PropertyInterceptionArgsCtor)); il.Emit(Codes.Store(args)); for (int i = 0; i < count; i++) { var inc = gInterceptors[i]; if (inc == null) { continue; } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyGetInterceptorOnGet)); } il.Position = leave; il.Finally(); for (int i = 0; i < count; i++) { var inc = gInterceptors[i]; if (inc == null) { continue; } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyGetInterceptorOnExit)); } il.Mark(cancel); il.EndTry(); il.Insert = CodeInsertion.After; if (setter != null || backing != null) { var unchanged = il.EmitLabel(); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsIsDirtyGet)); il.Emit(Codes.IfFalse(unchanged)); if (!getter.Target.IsStatic) { il.Emit(Codes.This); } if (backing == null) { var pcount = setter.Target.Parameters.Count - 1; for (int i = 0; i < pcount; i++) { il.Emit(Codes.Arg(setter.Target.Parameters[i])); } } il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsValueGet)); il.Emit(Codes.Unbox(type)); if (backing != null) { il.Emit(Codes.Store(backing)); } else { il.Emit(Codes.Invoke(setter.Target)); } il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsValueGet)); il.Emit(Codes.Unbox(type)); il.Emit(Codes.Store(result)); il.Emit(Codes.Nop); il.Mark(unchanged); } il.Emit(Codes.Load(result)); il.Body.InitLocals = true; il.Body.OptimizeMacros(); } if (setter != null && hasSetter) { var il = setter.GetIL(); il.Body.SimplifyMacros(); il.Position = il.GetFirst(); il.Insert = CodeInsertion.Before; var args = il.EmitLocal(Context.Finder.PropertyInterceptionArgs); var cancel = il.EmitLabel(); var argument = new Variable(setter.Target.Parameters.Last()); il.Try(); il.Emit(setter.Target.IsStatic ? Codes.Null : Codes.This); il.Emit(Codes.Load(info)); il.Emit(Codes.Load(argument)); il.Emit(Codes.Box(type)); il.Emit(Codes.Create(Context.Finder.PropertyInterceptionArgsCtor)); il.Emit(Codes.Store(args)); for (int i = 0; i < count; i++) { var inc = sInterceptors[i]; if (inc == null) { continue; } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertySetInterceptorOnSet)); } il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsIsDirtyGet)); il.Emit(Codes.IfFalse(cancel)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsValueGet)); il.Emit(Codes.Unbox(argument.Type)); il.Emit(Codes.Store(argument)); il.Emit(Codes.Nop); il.Position = il.Position.Previous; il.Mark(cancel); il.Position = il.GetLast(); il.Emit(Codes.Leave(il.Position)); il.Finally(); for (int i = 0; i < count; i++) { var inc = sInterceptors[i]; if (inc == null) { continue; } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertySetInterceptorOnExit)); } il.EndTry(); il.Body.InitLocals = true; il.Body.OptimizeMacros(); } }