private EntityDeclaration GenerateField( IField field, ICodeGeneratorProxy targetCodeBehind, string masterWrapperVariableName) { return (targetCodeBehind.CreateProperty( modifier: field.GetModifiersString(), returnTypeFullName: field.ReturnType.GetOriginalFullNameWithGlobal(), propertyName: field.Name, getterMethodBody: string.Format( "get{{ return {0}.{1}; }}", masterWrapperVariableName, field.Name), setterMethodBody: (field.IsConst || field.IsReadOnly) ? string.Empty : string.Format( "set{{ {0}.{1} = value; }}", masterWrapperVariableName, field.Name))); }
/// <summary> /// Generate code similar to: /// <code> /// <![CDATA[ /// public void __ActivateMixinDependencies(Target target) /// { /// ((IMixinDependency<T>)_mixinInstance).Dependency = mixinInstance; /// ((IMixinDependency<T>)_mixinInstance).OnDependencySet(); /// } /// ]]> /// </code> /// </summary> private void CreateActivateMixinDependenciesMethod( pMixinGeneratorPipelineState manager, ICodeGeneratorProxy wrapperClass) { const string targetMetherParameterVariableName = "target"; wrapperClass.CreateMethod( modifier: "public", returnTypeFullName: "void", methodName: ActivateMixinDependenciesMethodName, parameters: new[] { new KeyValuePair <string, string>( manager.GeneratedClass.ClassName, targetMetherParameterVariableName), }, methodBody: string.Join(Environment.NewLine, manager.CurrentpMixinAttribute.Mixin .GetAllBaseTypes() .Where(t => EnsureMixinDependenciesAreSatisfiedOnGeneratedClass.TypeIsIMixinDependency(t)) .Select(t => string.Format("(({0}){1}).Dependency = {2};(({0}){1}).OnDependencySet();", t.GetOriginalFullNameWithGlobal(), MixinInstanceDataMemberName, targetMetherParameterVariableName))) //Ensure the method is not created as MethodName(); but MethodName(){} + Environment.NewLine ); }
private EntityDeclaration GenerateProperty( MemberWrapper mw, ICodeGeneratorProxy targetCodeBehind, string masterWrapperVariableName) { var property = (IProperty)mw.Member; if (mw.ImplementationDetails.ImplementExplicitly) { return (targetCodeBehind.CreateProperty( modifier: string.Empty, returnTypeFullName: property.ReturnType.GetOriginalFullNameWithGlobal(), propertyName: property.IsIndexer ? string.Format( "{0}.this [{1} {2}]", mw.ImplementationDetails.ExplicitInterfaceImplementationType .GetOriginalFullNameWithGlobal(), property.Parameters.First().Type.GetOriginalFullNameWithGlobal(), property.Parameters.First().Name ) : mw.ImplementationDetails.ExplicitInterfaceImplementationType .GetOriginalFullNameWithGlobal() + "." + property.Name, getterMethodBody: GetPropertyGetterStatement(mw, masterWrapperVariableName), setterMethodBody: GetPropertySetterStatement(mw, masterWrapperVariableName))); } else { return (targetCodeBehind.CreateProperty( modifier: property.GetModifiersString( overrideModifiers: mw.ImplementationDetails.ImplementInTargetAsAbstract ? "abstract" : null), returnTypeFullName: property.ReturnType.GetOriginalFullNameWithGlobal(), propertyName: property.IsIndexer ? string.Format( "this [{0} {1}]", property.Parameters.First().Type.GetOriginalFullNameWithGlobal(), property.Parameters.First().Name ) : property.Name, getterMethodBody: GetPropertyGetterStatement(mw, masterWrapperVariableName), setterMethodBody: GetPropertySetterStatement(mw, masterWrapperVariableName))); } }
/// <summary> /// Create code similar to: /// <code> /// <![CDATA[ /// public System.Func<int,string> ProtectedVirtualMethodFunc { get; set; } /// /// public System.Func<string> PublicVirtualPropertyGetFunc { get; set; } /// public System.Action<string> PublicVirtualPropertySetFunc { get; set; } /// /// ]]></code> /// </summary> /// <param name="manager"></param> /// <param name="wrapperClass"></param> private void CreateVirtualMemberFunctions( pMixinGeneratorPipelineState manager, ICodeGeneratorProxy wrapperClass) { var membersThatNeedVirtualFuncs = manager.CurrentMixinMembers.Select(x => x.Member) .DistinctMembers() .Where( member => member.IsVirtual || member.IsOverride || member.IsOverridable); foreach (var member in membersThatNeedVirtualFuncs) { if (member is IMethod) { var propertyReturnType = (member as IMethod).ReturnType.Kind == TypeKind.Void ? "global::System.Action" : String.Format("global::System.Func<{0}>", string.Join(",", (member as IMethod).Parameters.Select(x => x.Type.GetOriginalFullNameWithGlobal()) .Union(member.ReturnType.GetFullTypeName()))); wrapperClass.CreateProperty( "public", propertyReturnType, this.GenerateVirtualMethodFuncName(member), "get;", "set;"); } else if (member is IProperty) { //Get if ((member as IProperty).CanGet && !(member as IProperty).Getter.IsPrivate) { wrapperClass.CreateProperty( "public", "global::System.Func<" + member.ReturnType.GetOriginalFullNameWithGlobal() + ">", GenerateVirtualMethodFuncName(member) + "Get", "get;", "set;"); } //Set if ((member as IProperty).CanSet && !(member as IProperty).Setter.IsPrivate) { wrapperClass.CreateProperty( "public", "global::System.Action<" + member.ReturnType.GetOriginalFullNameWithGlobal() + ">", GenerateVirtualMethodFuncName(member) + "Set", "get;", "set;"); } } } }
private void CreateRequirementsDataMemberAndConstructor( ICodeGeneratorProxy abstractWrapperCodeGenerator, MixinLevelCodeGeneratorPipelineState manager) { var requirementsVariableConstructorParameterName = RequirementsVariable.Replace("_", ""); var requirementsVariableTypeFullName = manager.RequirementsInterface .GetFullTypeName().EnsureStartsWith("global::"); var requirementsVariableConstructorParamater = new KeyValuePair <string, string>( //param type requirementsVariableTypeFullName, //param var name requirementsVariableConstructorParameterName); //_target = target; var requirementsVariableAssignmentExpression = string.Format("{0} = {1};", //data member RequirementsVariable, //equals constructor param name requirementsVariableConstructorParameterName); foreach (var constructor in manager.MixinGenerationPlan.AbstractWrapperPlan.Constructors) { //Add requirementsVariableConstructorParameterName //as first constructor argument var updatedParameters = new[] { requirementsVariableConstructorParamater } .Union( constructor.Parameters.ToKeyValuePair()) .ToList(); abstractWrapperCodeGenerator.CreateConstructor( modifiers: "public", parameters: updatedParameters, constructorInitializer: //pass original constructor arguments to original Mixin constructor ": base(" + string.Join(",", constructor.Parameters.Select(p => p.Name)) + ")", constructorBody: requirementsVariableAssignmentExpression ); } }
private void CreateRequirementsDataMember( ICodeGeneratorProxy codeGenerator, MixinLevelCodeGeneratorPipelineState manager) { codeGenerator.CreateDataMember( modifiers: "private readonly", dataMemberTypeFullName: manager.RequirementsInterface .GetFullTypeName().EnsureStartsWith("global::"), dataMemberName: RequirementsVariable); }
private void CreateRequirementsDataMemberAndConstructor( ICodeGeneratorProxy wrapperClass, pMixinGeneratorPipelineState manager) { wrapperClass.CreateDataMember( "private readonly", manager.CurrentMixinRequirementsInterface.EnsureStartsWith("global::"), RequirementsVariable); if (!manager.CurrentpMixinAttribute.ExplicitlyInitializeMixin && manager.CurrentpMixinAttribute.Mixin.GetConstructors() .Any(c => !c.Parameters.Any())) { //No explicit initialization, so just add a simple constructor //that takes a single parameter of type CurrentMixinRequirementsInterface wrapperClass.CreateConstructor( "public", new [] { new KeyValuePair <string, string>( manager.CurrentMixinRequirementsInterface.EnsureStartsWith("global::"), RequirementsVariable.Replace("_", "")) }, "", RequirementsVariable + "= " + RequirementsVariable.Replace("_", "") + ";"); return; } //Explicit initialization is needed, so wrap all existing constructors foreach (var constructor in manager.CurrentpMixinAttribute.Mixin.GetConstructors()) { var updatedParameters = constructor.Parameters.ToKeyValuePair(); updatedParameters.Insert(0, new KeyValuePair <string, string>( manager.CurrentMixinRequirementsInterface.EnsureStartsWith("global::"), RequirementsVariable.Replace("_", ""))); wrapperClass.CreateConstructor( "public", updatedParameters, ": base(" + string.Join(",", constructor.Parameters.Select(p => p.Name)) + ")", RequirementsVariable + "= " + RequirementsVariable.Replace("_", "") + ";"); } }
private void ProcessMembers(ICodeGeneratorProxy wrapperClass, pMixinGeneratorPipelineState manager) { var proxyMemberHelper = new CodeGeneratorProxyMemberHelper(wrapperClass, manager.BaseState.Context.TypeResolver.Compilation); proxyMemberHelper.CreateMembers( manager.CurrentMixinMembers.GetUnimplementedAbstractMembers(), generateMemberModifier: member => member.IsPublic ? "public override" : "protected override", generateReturnTypeFunc: member => member.ReturnType.GetOriginalFullNameWithGlobal(), baseObjectIdentifierFunc: member => RequirementsVariable, baseObjectMemberNameFunc: member => GenerateMixinImplementationRequirementsInterface.GetAbstractMemberImplementationName(member)); //Create public wrappers for the protected methods proxyMemberHelper.CreateMembers( manager.CurrentMixinMembers.GetUnimplementedAbstractMembers().Where(m => m.IsProtected), generateMemberModifier: member => "public", generateReturnTypeFunc: member => member.ReturnType.GetOriginalFullNameWithGlobal(), generateMemberNameFunc: member => GetProtectedMemberWrapperMemberName(member), baseObjectIdentifierFunc: member => "this"); }
private void ProcessMembers( ICodeGeneratorProxy abstractWrapperCodeGenerator, MixinLevelCodeGeneratorPipelineState manager) { var proxyMemberHelper = new CodeGeneratorProxyMemberHelper( abstractWrapperCodeGenerator, manager.CommonState.Context.TypeResolver.Compilation); proxyMemberHelper.CreateMembers( manager.MixinGenerationPlan.AbstractWrapperPlan.Members, generateMemberModifier: member => member.Member.GetModifiersString(overrideModifiers: "override"), generateReturnTypeFunc: member => member.Member.ReturnType.GetOriginalFullNameWithGlobal(), baseObjectIdentifierFunc: member => RequirementsVariable, baseObjectMemberNameFunc: member => member.ImplementationDetails.RequirementsInterfaceImplementationName); //There is a special case for protected abstract method. //Abstract methods can not have their access modifier //changed directly, so it is necessary to create //a public wrapper method. var abstractMembersToCreateAPublicWrapper = manager.MixinGenerationPlan.AbstractWrapperPlan.Members .Where(m => !string.IsNullOrEmpty( m.ImplementationDetails.ProtectedAbstractMemberPromotedToPublicMemberName)); proxyMemberHelper.CreateMembers( abstractMembersToCreateAPublicWrapper, generateMemberModifier: m => "public", generateReturnTypeFunc: m => m.Member.ReturnType.GetOriginalFullNameWithGlobal(), generateMemberNameFunc: m => m.ImplementationDetails.ProtectedAbstractMemberPromotedToPublicMemberName, //proxy to the protected member created above baseObjectIdentifierFunc: m => "this"); }
public CodeGeneratorProxyMemberHelper(ICodeGeneratorProxy codeGeneratorProxy, ICompilation compilation) { CodeGeneratorProxy = codeGeneratorProxy; Compilation = compilation; }
private void GenerateMembers( MixinLevelCodeGeneratorPipelineState manager, ICodeGeneratorProxy targetCodeBehind, IEnumerable <MemberWrapper> membersPromotedToTarget) { var compilation = manager.CommonState.Context.TypeResolver.Compilation; //__mixins.Test_ExampleMixin var masterWrapperVariableName = manager.MixinGenerationPlan.MasterWrapperPlan .MasterWrapperInstanceNameAvailableFromTargetCodeBehind; var masterWrapperStaticName = manager.MasterWrapper.GetFullTypeName(); foreach (var mw in membersPromotedToTarget) { EntityDeclaration newMemberDeclaration = null; if (mw.Member is IMethod) { newMemberDeclaration = GenerateMethod( mw, targetCodeBehind, compilation, mw.Member.IsStaticOrConst() ? masterWrapperStaticName : masterWrapperVariableName); } else if (mw.Member is IProperty) { newMemberDeclaration = GenerateProperty( mw, targetCodeBehind, mw.Member.IsStaticOrConst() ? masterWrapperStaticName : masterWrapperVariableName); } else if (mw.Member is IField) { newMemberDeclaration = GenerateField( mw.Member as IField, targetCodeBehind, mw.Member.IsStaticOrConst() ? masterWrapperStaticName : masterWrapperVariableName); } else { continue; } //Copy attributes from member to newMemberDeclaration newMemberDeclaration.Attributes.AddRange( mw.Member.MemberDefinition.Attributes .FilterOutNonInheritedAttributes() .ConvertToAttributeAstTypes() .Select(attributeAstType => new AttributeSection(attributeAstType))); } }
public MasterWrapperCodeGeneratorProxyMemberHelper(ICodeGeneratorProxy codeGeneratorProxy, ICompilation compilation) : base(codeGeneratorProxy, compilation) { }
/// <summary> /// Wrap every non-private member in current pMixin with special /// handling for static and virtual members /// </summary> /// <param name="manager"></param> /// <param name="wrapperClass"></param> private void ProcessMembers(pMixinGeneratorPipelineState manager, ICodeGeneratorProxy wrapperClass) { var proxyMemberHelper = new MasterWrapperCodeGeneratorProxyMemberHelper(wrapperClass, manager.BaseState.Context.TypeResolver.Compilation); //Static Members proxyMemberHelper.CreateMembers( manager.CurrentMixinMembers .Select(x => x.Member) .DistinctMembers() .Where(member => member.IsStatic), generateMemberModifier: member => "internal static", baseObjectIdentifierFunc: member => manager.CurrentpMixinAttribute.Mixin.IsStaticOrSealed() ? manager.CurrentpMixinAttribute.Mixin.GetOriginalFullNameWithGlobal() : manager.CurrentMixinAbstractMembersWrapperClass.Name ); //Regular Members proxyMemberHelper.CreateMembers( manager.CurrentMixinMembers .Select(x => x.Member) .DistinctMembers() .Where( member => !member.IsStatic && !(member.IsAbstract && member.IsProtected) && !member.IsOverride && !member.IsOverridable && !member.IsVirtual), generateMemberModifier: member => "internal", baseObjectIdentifierFunc: member => MixinInstanceDataMemberName); //Protected Abstract Members proxyMemberHelper.CreateMembers( manager.CurrentMixinMembers .Select(x => x.Member) .DistinctMembers() .Where(member => (member.IsAbstract || member.IsOverride) && member.IsProtected), generateMemberModifier: member => "internal", baseObjectIdentifierFunc: member => MixinInstanceDataMemberName, baseObjectMemberNameFunc: member => GenerateAbstractMixinMembersWrapperClass.GetProtectedMemberWrapperMemberName(member)); //Virtual Members foreach ( var member in manager.CurrentMixinMembers .Select(x => x.Member) .DistinctMembers() .Where(member => member.IsVirtual || (member.IsOverride || member.IsOverridable && !member.IsProtected))) { #region Virtual Method if (member is IMethod) { //Virtual methods call to the Virtual Method Func wrapperClass.CreateMethod( "internal", member.ReturnType.GetOriginalFullNameWithGlobal(), member.Name, (member as IMethod).Parameters.ToKeyValuePair(), string.Format("{0} {1}({2});", (member as IMethod).GetReturnString(), GenerateVirtualMethodFuncName(member), string.Join(",", (member as IMethod).Parameters.Select(x => x.Name))), (member as IMethod).GetGenericMethodConstraints( manager.BaseState.Context.TypeResolver.Compilation)); } #endregion #region Virtual Property else if (member is IProperty) { wrapperClass.CreateProperty( "internal", member.ReturnType.GetOriginalFullNameWithGlobal(), member.Name, (member as IProperty).CanGet && !(member as IProperty).Getter.IsPrivate ? string.Format("get{{ return {0}(); }}", GenerateVirtualMethodFuncName(member) + "Get") : "", (member as IProperty).CanSet && !(member as IProperty).Setter.IsPrivate ? string.Format("set {{{0}(value); }}", GenerateVirtualMethodFuncName(member) + "Set") : "" ); } #endregion } }
private string CreateConstructorInitializersForVirtualMemberFunctions( pMixinGeneratorPipelineState manager, ICodeGeneratorProxy wrapperClass) { var proxyMemberHelper = new MasterWrapperCodeGeneratorProxyMemberHelper(wrapperClass, manager.BaseState.Context.TypeResolver.Compilation); var sb = new StringBuilder(); foreach ( var member in manager.CurrentMixinMembers .Select(x => x.Member) .DistinctMembers() .Where(member => !member.IsPrivate && (member.IsVirtual || member.IsOverride || member.IsOverridable))) { if (member is IMethod) { //ProtectedVirtualMethodFunc = (i) => AbstractWrapper.ProtectedVirtualMethod(i); sb.AppendFormat("{0} = ({1}) => {2};", GenerateVirtualMethodFuncName(member), string.Join(",", (member as IMethod).Parameters.Select(x => x.Name)), proxyMemberHelper.GetMethodBodyCallStatement( member as IMethod, (m) => MixinInstanceDataMemberName, (m) => m.IsProtected ? GenerateAbstractMixinMembersWrapperClass.GetProtectedMemberWrapperMemberName(m) : m.Name)); } else if (member is IProperty) { if ((member as IProperty).CanGet) { //PublicVirtaulPropertyFuncGet = () => AbstractWrapper.PublicVirtualProperty; sb.AppendFormat( @"{0}Get = () => {1};", GenerateVirtualMethodFuncName(member), proxyMemberHelper.GetPropertyGetterReturnBodyStatement( member as IProperty, (m) => MixinInstanceDataMemberName, (m) => m.IsProtected ? GenerateAbstractMixinMembersWrapperClass.GetProtectedMemberWrapperMemberName(m) : m.Name)); } if ((member as IProperty).CanSet) { //PublicVirtualPropertySetFunc = (s) => AbstractWrapper.PublicVirtualProperty = s; sb.AppendFormat( @"{0}Set = (value) => {1};", GenerateVirtualMethodFuncName(member), proxyMemberHelper.GetPropertySetterReturnBodyStatement( member as IProperty, (m) => MixinInstanceDataMemberName, (m) => m.IsProtected ? GenerateAbstractMixinMembersWrapperClass.GetProtectedMemberWrapperMemberName(m) : m.Name)); } } } return(sb.ToString()); }
/// <summary> /// Generate code similar to: /// <code> /// <![CDATA[ /// AbstractWrapper _host; /// /// public TargetWrapper(IMixinRequirements host){ _host = host; } /// ]]> /// </code> /// </summary> private void CreateConstructorAndRequirementsInterfaceDataMember( pMixinGeneratorPipelineState manager, ICodeGeneratorProxy wrapperClass) { var mixinInstanceType = ""; #region Assign Mixin Instance Type if (manager.CurrentpMixinAttribute.Mixin.GetDefinition().IsAbstract) { //Abstract Mixin Wrapper is in a different namespace, so we need the fullname mixinInstanceType = ExternalGeneratedNamespaceHelper.GenerateChildClassFullName( manager, GenerateAbstractMixinMembersWrapperClass.GetWrapperClassName(manager)); } else if (manager.CurrentMixinMembers.Any(x => x.Member.IsProtected)) { //Abstract Mixin Wrapper is in the same namespace mixinInstanceType = GenerateAbstractMixinMembersWrapperClass.GetWrapperClassName(manager); } else { mixinInstanceType = manager.CurrentpMixinAttribute.Mixin.GetOriginalFullNameWithGlobal(); } #endregion //add data member wrapperClass.CreateDataMember( /* Can't remember why it was necessary to have a modifier other than public * manager.CurrentpMixinAttribute.Mixin.GetDefinition().IsPublic * ? "public" * : manager.CurrentpMixinAttribute.Mixin.GetDefinition().IsInternal * ? "internal" * : "private" */"public" + " readonly", mixinInstanceType, MixinInstanceDataMemberName); string mixinInstanceInitialization; #region Create Mixin Instance (InitializeMixin / TryActivateMixin if (manager.CurrentpMixinAttribute.ExplicitlyInitializeMixin) { mixinInstanceInitialization = string.Format("(({0}){1}).{2}();", AddMixinConstructorRequirementDependency .GetMixinConstructorRequirement(manager), MixinInstanceDataMemberName.Replace("_", ""), "InitializeMixin"); } else if (manager.CurrentpMixinAttribute.Mixin.GetDefinition().IsSealed) { mixinInstanceInitialization = string.Format("base.TryActivateMixin<{0}>();", manager.CurrentpMixinAttribute.Mixin.GetOriginalFullNameWithGlobal()); } else if (manager.CurrentpMixinAttribute.Mixin.GetDefinition().IsAbstract) { mixinInstanceInitialization = string.Format("base.TryActivateMixin<{0}>({1});", mixinInstanceType, MixinInstanceDataMemberName.Replace("_", "")); } else { mixinInstanceInitialization = string.Format("base.TryActivateMixin<{0}>({1});", GenerateMixinSpecificAutoGeneratedClass.GetFullNameForChildType( manager, GenerateAbstractMixinMembersWrapperClass.GetWrapperClassName(manager)), MixinInstanceDataMemberName.Replace("_", "")); } #endregion var initializeBaseExpression = #region base.Initialize string.Format("base.Initialize( {0}, {1}, new global::{2}<global::{3}>{{ {4} }});", MixinInstanceDataMemberName.Replace("_", ""), MixinInstanceDataMemberName, "System.Collections.Generic.List", typeof(IMixinInterceptor), string.Join(",", manager.CurrentpMixinAttribute.Interceptors .Select(x => x.GenerateActivationExpression()) ) ); #endregion wrapperClass.CreateConstructor( "public", new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>( manager.CurrentMixinRequirementsInterface.EnsureStartsWith("global::"), MixinInstanceDataMemberName.Replace("_", "")) }, constructorInitializer: "", constructorBody: MixinInstanceDataMemberName + " = " + mixinInstanceInitialization + CreateConstructorInitializersForVirtualMemberFunctions(manager, wrapperClass) + initializeBaseExpression ); }
private EntityDeclaration GenerateMethod( MemberWrapper mw, ICodeGeneratorProxy targetCodeBehind, ICompilation compilation, string masterWrapperVariableName) { var method = (IMethod)mw.Member; if (mw.ImplementationDetails.ImplementExplicitly) { return (targetCodeBehind.CreateMethod( modifier: string.Empty, returnTypeFullName: method.ReturnType.GetOriginalFullNameWithGlobal(), methodName: mw.ImplementationDetails.ExplicitInterfaceImplementationType .GetOriginalFullNameWithGlobal() + "." + method.Name, parameters: method.Parameters.ToKeyValuePair(), methodBody: string.Format( "{0} (({1}){2}).{3}({4});", (mw.Member.ReturnType.Kind == TypeKind.Void) ? string.Empty : "return", mw.ImplementationDetails.ExplicitInterfaceImplementationType .GetOriginalFullNameWithGlobal(), masterWrapperVariableName, method.GetOriginalName(), string.Join(",", method.Parameters.Select(x => x.Name))), constraingClause: method.GetGenericMethodConstraints(compilation))); } else { return (targetCodeBehind.CreateMethod( modifier: method.GetModifiersString( overrideModifiers: mw.ImplementationDetails.ImplementInTargetAsAbstract ? "abstract" : null), returnTypeFullName: method.ReturnType.GetOriginalFullNameWithGlobal(), methodName: method.GetOriginalName(), parameters: method.Parameters.ToKeyValuePair(), methodBody: mw.ImplementationDetails.ImplementInTargetAsAbstract ? string.Empty : string.Format( "{0} {1}.{2}({3});", (method.ReturnType.Kind == TypeKind.Void) ? string.Empty : "return", masterWrapperVariableName, method.GetOriginalName(), string.Join(",", method.Parameters.Select(x => x.Name))), constraingClause: method.GetGenericMethodConstraints(compilation))); } }