protected virtual void EmitPlainCompositeHashCode( CompositeCodeGenerationInfo codeGenerationInfo, CompositeModel compositeModel, CompositeTypeModel typeModel, CompositeTypeGenerationInfo publicCompositeGenInfo, CompositeTypeGenerationInfo thisGenInfo, CompositeEmittingInfo emittingInfo, IEnumerable <FragmentTypeGenerationInfo> fragmentGenerationInfos ) { this.EmitCallNonCompositeMethod( codeGenerationInfo, compositeModel, typeModel, publicCompositeGenInfo, thisGenInfo, emittingInfo, fragmentGenerationInfos, HASH_CODE_METHOD, null, null, genInfos => genInfos.FirstOrDefault(genInfo => { var result = thisGenInfo.Parents.Keys.Where(t => !thisGenInfo.Builder.Equals(t)).OnlyBottomTypes().Where(t => !OBJECT_TYPE.Equals(t)).Any(p => genInfo.Parents.ContainsKey(p.GenericDefinitionIfGArgsHaveGenericParams())) || genInfo.DirectBaseFromModel.GetFullInheritanceChain().Any(t => compositeModel.ApplicationModel.GenericFragmentBaseType.NewWrapperAsType(this.ctx).Equals(t)); if (result) { var m = TypeGenerationUtils.FindMethodImplicitlyImplementingMethod(genInfo.DirectBaseFromModel, HASH_CODE_METHOD); result = !HASH_CODE_METHOD.Equals(m); } return(result); }) ); }
public AbstractModelTypeModelScopeSupportBase(CompositeModelTypeAssemblyScopeSupport assemblyScopeSupport, CompositeCodeGenerationInfo codeGenerationInfo) { ArgumentValidator.ValidateNotNull("Assembly-scope support", assemblyScopeSupport); ArgumentValidator.ValidateNotNull("Composite code generation info", codeGenerationInfo); this._assemblyScopeSupport = assemblyScopeSupport; this._codeGenerationInfo = codeGenerationInfo; }
protected override void EmitPublicCompositeHashCode( CompositeCodeGenerationInfo codeGenerationInfo, CompositeModel compositeModel, CompositeTypeModel typeModel, CompositeTypeGenerationInfo publicCompositeGenInfo, CompositeTypeGenerationInfo thisGenInfo, CompositeEmittingInfo emittingInfo, IEnumerable <FragmentTypeGenerationInfo> fragmentGenerationInfos ) { this.EmitPlainCompositeHashCode(codeGenerationInfo, compositeModel, typeModel, publicCompositeGenInfo, thisGenInfo, emittingInfo, fragmentGenerationInfos); }
protected static Type GetParticipantType(Type type, CompositeModel model, CompositeCodeGenerationInfo codeGenerationInfo, EventHandler <AssemblyLoadingArgs> loadingEvt, IDictionary <Assembly, Assembly> assDic, String prefix, Boolean useBaseType = false) { return(GetGeneratedPublicType(type, model, codeGenerationInfo, loadingEvt, assDic) #if WINDOWS_PHONE_APP .GetTypeInfo().DeclaredNestedTypes.Select(t => t.AsType()) #else .GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic) #endif .FirstOrDefault(tt => tt.Name.StartsWith(prefix) && (useBaseType ? tt.GetBaseType().GetGenericDefinitionIfContainsGenericParameters().Equals(type) : tt.GetAllParentTypes().Any(ttt => ttt.GetGenericDefinitionIfContainsGenericParameters().Equals(type))) //&& !TypeUtil.TypesOf( tt ).Except( new Type[] { tt, type } ).Any( ttt => TypeUtil.IsAssignableFrom( TypeUtil.GenericDefinitionIfContainsGenericParams( type ), ttt ) ) )); }
protected virtual void EmitPropertySetterMethod( CompositeCodeGenerationInfo codeGenerationInfo, PropertyModel propertyModel, CompositeTypeGenerationInfo publicCompositeGenInfo, CompositeTypeGenerationInfo thisGenerationInfo, CILField propertyField, CILTypeBase fieldType, CILTypeBase propertyType, CompositeMethodGenerationInfo methodGenInfo, Action <CILField, MethodIL> writeAction ) { // Code for setting properties: // internal void Property<idx>Setter(<property type> value ) // { // CompositeInstance instance = this._instance; // <if the property is immutable> // if ( !this._instance.IsPrototype ) // { // throw new InvalidOperationException( "Can not set immutable propery " + QualifiedName.FromTypeAndName( <declaring type>, <name> ) + " for a non-prototype composite instance." ); // } // <end if> // <write property field> // } var il = methodGenInfo.IL; il.EmitLoadThisField(thisGenerationInfo.CompositeField) .EmitStoreLocal(methodGenInfo.GetOrCreateLocal(LB_C_INSTANCE, codeGenerationInfo.CompositeInstanceFieldType.NewWrapper(this.ctx))); this.EmitThrowIfApplicationNotActive(methodGenInfo); this.EmitProcessParameters(codeGenerationInfo, propertyModel.SetterMethod, true, publicCompositeGenInfo, thisGenerationInfo, methodGenInfo); this.EmitThrowIfViolations(thisGenerationInfo, methodGenInfo, propertyModel.SetterMethod); this.EmitCheckPropertyImmutability(propertyModel, thisGenerationInfo, il); writeAction(propertyField, il); il .EmitPop() .EmitReturn(); }
protected override void EmitTheRestOfPublicCompositeConstructor( CompositeCodeGenerationInfo codeGenerationInfo, CompositeModel model, CompositeTypeModel typeModel, CompositeEmittingInfo emittingInfo, IEnumerable <FragmentTypeGenerationInfo> fragmentGenerationInfos, CompositeTypeGenerationInfo thisGenerationInfo, ConstructorGenerationInfo ctorGenerationInfo, Int32 firstAdditionalParameterIndex ) { base.EmitTheRestOfPublicCompositeConstructor(codeGenerationInfo, model, typeModel, emittingInfo, fragmentGenerationInfos, thisGenerationInfo, ctorGenerationInfo, firstAdditionalParameterIndex); Int32 baseAdditionalParamsCount = base.GetAmountOfAdditionalArgumentsForPublicCompositeConstructor(); this.EmitSetActionMethod <ActivateAttribute>( codeGenerationInfo, model, typeModel, fragmentGenerationInfos, thisGenerationInfo, thisGenerationInfo, emittingInfo, ctorGenerationInfo, firstAdditionalParameterIndex + baseAdditionalParamsCount, ACTIVATION_METHOD_NAME, false ); this.EmitSetActionMethod <PassivateAttribute>( codeGenerationInfo, model, typeModel, fragmentGenerationInfos, thisGenerationInfo, thisGenerationInfo, emittingInfo, ctorGenerationInfo, firstAdditionalParameterIndex + baseAdditionalParamsCount + 1, PASSIVATION_METHOD_NAME, true ); }
protected virtual void EmitPropertyGetterMethod( CompositeCodeGenerationInfo codeGenerationInfo, PropertyModel propertyModel, CompositeTypeGenerationInfo publicCompositeGenInfo, CompositeTypeGenerationInfo thisGenerationInfo, CILField propertyField, CILTypeBase propertyType, CompositeMethodGenerationInfo methodGenInfo, Action <CILField, MethodIL> readAction ) { // Code for getting properties: // public <property type> Property<idx>Getter( ) // { // CompositeInstance instance = this._instance; // <check application active> // var result = <read property field>; // <check constraints> // return result; // } var il = methodGenInfo.IL; il.EmitLoadThisField(thisGenerationInfo.CompositeField) .EmitStoreLocal(methodGenInfo.GetOrCreateLocal(LB_C_INSTANCE, codeGenerationInfo.CompositeInstanceFieldType.NewWrapper(this.ctx))); this.EmitThrowIfApplicationNotActive(methodGenInfo); var resultB = methodGenInfo.GetOrCreateLocal(LB_RESULT, methodGenInfo.ReturnType); readAction(propertyField, il); il.EmitStoreLocal(resultB); this.EmitProcessParameters(codeGenerationInfo, propertyModel.GetterMethod, false, publicCompositeGenInfo, thisGenerationInfo, methodGenInfo); this.EmitProcessResult(codeGenerationInfo, propertyModel.GetterMethod, publicCompositeGenInfo, thisGenerationInfo, methodGenInfo); this.EmitThrowIfViolations(thisGenerationInfo, methodGenInfo, propertyModel.GetterMethod); il.EmitLoadLocal(resultB) .EmitReturn(); }
protected virtual void EmitPlainCompositeEquals( CompositeCodeGenerationInfo codeGenerationInfo, CompositeModel compositeModel, CompositeTypeModel typeModel, CompositeTypeGenerationInfo publicCompositeGenInfo, CompositeTypeGenerationInfo thisGenInfo, CompositeEmittingInfo emittingInfo, IEnumerable <FragmentTypeGenerationInfo> fragmentGenerationInfos ) { // return Object.ReferenceEquals(this, obj) || (obj is <composite type> && <equals-implementation>); ILLabel?returnTrueL = null; ILLabel?returnFalseL = null; this.EmitCallNonCompositeMethod( codeGenerationInfo, compositeModel, typeModel, publicCompositeGenInfo, thisGenInfo, emittingInfo, fragmentGenerationInfos, EQUALS_METHOD, il => { // Make labels for true and false values returnTrueL = il.DefineLabel(); returnFalseL = il.DefineLabel(); il.EmitLoadArg(0) .EmitLoadArg(1) .EmitCall(REFERENCE_EQUALS_METHOD) .EmitBranch(BranchType.IF_TRUE, returnTrueL.Value); var continueLabel = il.DefineLabel(); foreach (var parent in thisGenInfo.Parents.Values.OnlyBottomTypes()) { il.EmitLoadArg(1) .EmitIsInst(parent) .EmitBranch(BranchType.IF_TRUE, continueLabel); } il.EmitBranch(BranchType.ALWAYS, returnFalseL.Value) .MarkLabel(continueLabel); }, il => { // return true il.MarkLabel(returnTrueL.Value) .EmitLoadBoolean(true) .EmitReturn() // return false .MarkLabel(returnFalseL.Value) .EmitLoadBoolean(false) .EmitReturn(); }, genInfos => genInfos.FirstOrDefault(genInfo => { var result = thisGenInfo.Parents.Keys.Where(t => !thisGenInfo.Builder.Equals(t)).OnlyBottomTypes().Where(t => !OBJECT_TYPE.Equals(t)).Any(p => genInfo.Parents.ContainsKey(p.GenericDefinitionIfGArgsHaveGenericParams())) || genInfo.DirectBaseFromModel.GetFullInheritanceChain().Any(t => compositeModel.ApplicationModel.GenericFragmentBaseType.NewWrapperAsType(this.ctx).Equals(t)); if (result) { var m = TypeGenerationUtils.FindMethodImplicitlyImplementingMethod(genInfo.DirectBaseFromModel, EQUALS_METHOD); result = !EQUALS_METHOD.Equals(m); } return(result); }) ); }
protected virtual void EmitPropertyRelatedThings( CompositeCodeGenerationInfo codeGenerationInfo, CompositeTypeGenerationInfo publicCompositeGenInfo, CompositeTypeGenerationInfo thisGenerationInfo, CompositeMethodGenerationInfo thisMethodGenerationInfo, PropertyModel propertyModel, Type genericPropertyMixinType ) { var nPropertyInfo = propertyModel.NativeInfo; var propertyInfo = nPropertyInfo.NewWrapper(this.ctx); if (this.IsCompositeGeneratedProperty(thisGenerationInfo, propertyModel, genericPropertyMixinType)) { var propertyIdx = thisGenerationInfo.AutoGeneratedPropertyInfos.Count; var propertyType = TypeGenerationUtils.CreateTypeForEmitting(propertyInfo.GetPropertyType(), thisGenerationInfo.GenericArguments, null); CILTypeBase fieldType; Action <CILField, MethodIL> readMethod; Action <CILField, MethodIL> read32Method; Action <CILField, MethodIL> writeMethod; Action <CILField, MethodIL> compareExchangeMethodEmitter; this.GetReadAndWriteMethods(propertyType, out readMethod, out read32Method, out writeMethod, out compareExchangeMethodEmitter, out fieldType); // Field: // private <property type or Object> _property<idx>; var propertyField = thisGenerationInfo.Builder.AddField( PROPERTY_FIELD_PREFIX + propertyIdx, fieldType, FieldAttributes.Private ); // Field getter var getter = thisGenerationInfo.Builder.AddMethod( PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_GETTER_POSTFIX, MethodAttributes.Private | MethodAttributes.HideBySig, CallingConventions.HasThis); this.EmitPropertyGetterMethod(codeGenerationInfo, propertyModel, publicCompositeGenInfo, thisGenerationInfo, propertyField, propertyType, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(getter, null, null).WithReturnType(propertyType) /*.WithParameters( propertyInfo.GetIndexParameters().Select( p => Tuple.Create( p.ParameterType, p.Attributes ) ) )*/, readMethod); // Field getter for 32-bit processes, if required CILMethod getter32 = null; if (read32Method != null) { getter32 = thisGenerationInfo.Builder.AddMethod( PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_GETTER32_POSTFIX, MethodAttributes.Private | MethodAttributes.HideBySig, CallingConventions.HasThis); this.EmitPropertyGetterMethod(codeGenerationInfo, propertyModel, publicCompositeGenInfo, thisGenerationInfo, propertyField, propertyType, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(getter32, null, null).WithReturnType(propertyType) /*.WithParameters( propertyInfo.GetIndexParameters().Select( p => Tuple.Create( p.ParameterType, p.Attributes ) ) )*/, read32Method); } // Field setter var setter = thisGenerationInfo.Builder.AddMethod( PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_SETTER_POSTFIX, MethodAttributes.Public | MethodAttributes.HideBySig, // TODO MethodAttributes.Assembly when [InternalsVisibleTo(...)] attribute will be applied to all generated assemblies. CallingConventions.HasThis); this.EmitPropertySetterMethod(codeGenerationInfo, propertyModel, publicCompositeGenInfo, thisGenerationInfo, propertyField, fieldType, propertyType, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(setter, null, null).WithParameters(Enumerable.Repeat(Tuple.Create(propertyType, ParameterAttributes.None), 1)), writeMethod); // Exchange method var exchangeMethod = thisGenerationInfo.Builder.AddMethod( PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_EXCHANGE_POSTFIX, MethodAttributes.Private | MethodAttributes.HideBySig, CallingConventions.HasThis); this.EmitPropertyExchangeMethod(propertyModel, thisGenerationInfo, propertyField, fieldType, propertyType, setter, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(exchangeMethod, null, null).WithReturnType(propertyType).WithParameters(Enumerable.Repeat(Tuple.Create(propertyType, ParameterAttributes.None), 1)), writeMethod); // CompareExchange method var compareExchangeMethod = thisGenerationInfo.Builder.AddMethod( PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_COMPARE_EXCHANGE_POSTFIX, MethodAttributes.Private | MethodAttributes.HideBySig, CallingConventions.HasThis); this.EmitPropertyCompareExchangeMethod(propertyModel, thisGenerationInfo, propertyField, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(compareExchangeMethod, null, null).WithReturnType(propertyType).WithParameters(Enumerable.Repeat(Tuple.Create(propertyType, ParameterAttributes.None), 2)), compareExchangeMethodEmitter); thisGenerationInfo.AutoGeneratedPropertyInfos.Add(nPropertyInfo, new PropertyGenerationInfo( this.EmitRefMethodForPropertyOrEvent(propertyField, PROPERTY_METHOD_PREFIX + propertyIdx + REF_INVOKER_METHOD_SUFFIX), propertyModel, propertyField, getter, getter32, setter, exchangeMethod, compareExchangeMethod, propertyType )); } if (this.NeedToEmitAdditionalMemberInfo(thisGenerationInfo, propertyInfo.Name, (parent, name) => parent.DeclaredProperties.FirstOrDefault(p => Object.Equals(p.Name, name)))) { // Need to define property if we inherit property directly from interface var name = propertyInfo.Name; if (thisGenerationInfo.RawPropertyInfos.Keys.Any(pInfo => pInfo.Name.Equals(name))) { // We already have property with the same name from different type name = QualifiedName.FromMemberInfo(nPropertyInfo).ToString(); } CILProperty pBuilder; if (!thisGenerationInfo.RawPropertyInfos.TryGetValue(nPropertyInfo, out pBuilder)) { pBuilder = thisGenerationInfo.Builder.AddProperty( name, propertyInfo.Attributes ); thisGenerationInfo.RawPropertyInfos.Add(nPropertyInfo, pBuilder); } if (thisMethodGenerationInfo.MethodFromModel.Equals(propertyInfo.GetMethod)) { pBuilder.GetMethod = thisMethodGenerationInfo.Builder; } else if (thisMethodGenerationInfo.MethodFromModel.Equals(propertyInfo.SetMethod)) { pBuilder.SetMethod = thisMethodGenerationInfo.Builder; } else { throw new InternalException("Found a property, but neither setter nor getter matched the method being emitted. Property is " + propertyInfo + ", method is " + thisMethodGenerationInfo.MethodFromModel + "."); } } }
protected static Type GetGeneratedPublicType(Type type, CompositeModel model, CompositeCodeGenerationInfo codeGenerationInfo, EventHandler <AssemblyLoadingArgs> loadingEvt, IDictionary <Assembly, Assembly> assDic) { return(assDic.GetOrAdd_NotThreadSafe( type.GetAssembly(), a => ReflectionHelper.QI4CS_ASSEMBLY.Equals(a) ? assDic[model.MainCodeGenerationType.GetAssembly()] : DoLoadGeneratedAssembly(a, model.ApplicationModel, loadingEvt) ).GetType( codeGenerationInfo.PublicCompositePrefix + model.CompositeModelID, true )); }
public PublicCompositeTypeGenerationResultImpl( CompositeModel cModel, CompositeTypeModel tModel, EventHandler <AssemblyLoadingArgs> loadingEvt, IDictionary <Assembly, Assembly> assDic, CompositeCodeGenerationInfo codeGenerationInfo ) { //var orderer = new TypeLoadOrderer( cModel ); var collectionsFactory = cModel.ApplicationModel.CollectionsFactory; var publicTypes = cModel .GetAllCompositeTypes() .Concat(cModel.GetAllFragmentTypes()) //.OrderBy( t => t, orderer ) .Where(t => cModel.ApplicationModel.AffectedAssemblies.Contains(t.GetAssembly())) .OrderBy(t => t.Equals(cModel.MainCodeGenerationType) ? 0 : 1) // Populate main code generation type first .Select(t => GetGeneratedPublicType(t, cModel, codeGenerationInfo, loadingEvt, assDic)) .Distinct() .ToArray(); var mainTypes = publicTypes.Where(iResult => iResult.IsPublicTypeMainCompositeType()); if (!mainTypes.Any() || mainTypes.Skip(1).Any()) { throw new ArgumentException((mainTypes.Any() ? "Too many" : "Too little") + " generated main types (" + String.Join(", ", mainTypes) + "), exactly one allowed."); } var mainType = mainTypes.First(); this._compositeFactory = (CompositeFactory)mainType.GetAssembly().GetType(mainType.Name + codeGenerationInfo.CompositeFactorySuffix, true) #if WINDOWS_PHONE_APP .GetAllInstanceConstructors().First() #else .GetConstructors()[0] #endif .Invoke(null); var fragmentTypeGenerationResults = tModel.FragmentTypeInfos.Keys //.OrderBy( t => t, orderer ) .Select(t => Tuple.Create(t, GetParticipantType(t, cModel, codeGenerationInfo, loadingEvt, assDic, codeGenerationInfo.FragmentPrefix, true))) .Where(t => t.Item2 != null) .Select(t => (FragmentTypeGenerationResult) new FragmentTypeGenerationResultImpl(t.Item1, t.Item2)) .ToArray(); var concernInvocationGenerationResults = tModel.ConcernInvocationTypeInfos.Keys //.OrderBy( t => t, orderer ) .Select(t => Tuple.Create(t, GetParticipantType(t, cModel, codeGenerationInfo, loadingEvt, assDic, codeGenerationInfo.ConcernInvocationPrefix))) .Where(t => t.Item2 != null) .Select(t => (TypeGenerationResult) new TypeGenerationResultImpl(t.Item2, t.Item1)) .ToArray(); var sideEffectInvocationGenerationResults = tModel.SideEffectInvocationTypeInfos.Keys //.OrderBy( t => t, orderer ) .Select(t => Tuple.Create(t, GetParticipantType(t, cModel, codeGenerationInfo, loadingEvt, assDic, codeGenerationInfo.SideEffectInvocationPrefix))) .Where(t => t.Item2 != null) .Select(t => (TypeGenerationResult) new TypeGenerationResultImpl(t.Item2, t.Item1)) .ToArray(); var privateCompositeGenerationresults = tModel.PrivateCompositeTypeInfos.Keys //.OrderBy( t => t, orderer ) .Select(t => Tuple.Create(t, GetParticipantType(t, cModel, codeGenerationInfo, loadingEvt, assDic, codeGenerationInfo.PrivateCompositePrefix))) .Where(t => t.Item2 != null) .Select(t => (TypeGenerationResult) new TypeGenerationResultImpl(t.Item2, t.Item1)) .ToArray(); var pGArgs = collectionsFactory.NewDictionaryProxy( tModel.PublicCompositeGenericArguments .Select((gArg, idx) => Tuple.Create(gArg, idx)) .GroupBy(tuple => tuple.Item1.DeclaringType) .ToDictionary(grouping => grouping.Key, grouping => collectionsFactory.NewListProxy(grouping.Select(tuple => tuple.Item2).ToList()).CQ)); this._generatedPublicMainType = mainType; this._maxParamCountForCtors = mainType #if WINDOWS_PHONE_APP .GetAllInstanceConstructors().First() #else .GetConstructors(BindingFlags.Instance | BindingFlags.Public)[0] #endif .GetParameters().Length; this._generatedPublicTypes = collectionsFactory.NewListProxy(publicTypes.Select( pt => (GeneratedTypeInfo) new GeneratedTypeInfoImpl(pt)) .ToList()).CQ; this._publicCompositeGenericArguments = pGArgs.CQ; this._privateCompositeGenerationResults = collectionsFactory.NewListProxyFromParams(privateCompositeGenerationresults).CQ; this._fragmentGenerationResults = collectionsFactory.NewListProxyFromParams(fragmentTypeGenerationResults).CQ; this._concernInvocationGenerationResults = collectionsFactory.NewListProxyFromParams(concernInvocationGenerationResults).CQ; this._sideEffectInvocationGenerationResults = collectionsFactory.NewListProxyFromParams(sideEffectInvocationGenerationResults).CQ; // Remember to remove Qi4CS assembly if present assDic.Remove(ReflectionHelper.QI4CS_ASSEMBLY); }