private void AddProxyInfo(ClassNotation @class, ProxyGeneratorContext context, ITypeSymbolInfo type) { @class.Members.Add(new FieldNotation() { Accessibility = AccessibilityInfo.Public, Type = type.FullName, Name = context.GetProxyFieldName() }); var setProxyNode = new MethodNotation() { Accessibility = AccessibilityInfo.Public, ReturnType = "void", Name = "SetProxy" }; setProxyNode.Parameters.Add(new ParameterNotation() { Type = "object", Name = "instance" }); setProxyNode.Parameters.Add(new ParameterNotation() { Type = "System.IServiceProvider", Name = "serviceProvider" }); setProxyNode.Body.AddRange(Notation.Create(context.GetProxyFieldName(), " = instance as ", type.FullName, ";")); @class.Members.Add(setProxyNode); @class.Inherits.Add("Norns.Destiny.AOP.IInterceptProxy".ToNotation()); foreach (var f in @class.Members.Select(i => i as FieldNotation).Where(i => i != null && i.IsFromDI)) { setProxyNode.Body.AddRange(Notation.Create(f.Name, " = serviceProvider.GetService(typeof(", f.Type, ")) as ", f.Type, ";")); } }
public static string GetReturnValueParameterName(this ProxyGeneratorContext context) { if (!context.ContainsKey(ReturnValueParameterName)) { context.Add(ReturnValueParameterName, $"r{RandomUtils.NewName()}"); } return(context[ReturnValueParameterName].ToString()); }
public static string GetProxyFieldName(this ProxyGeneratorContext context) { var c = context.Parent ?? context; if (!c.ContainsKey(ProxyFieldName)) { c.Add(ProxyFieldName, $"f{RandomUtils.NewName()}"); } return(c[ProxyFieldName].ToString()); }
public override INotation CreateImplement(ITypeSymbolInfo type) { var @namespace = new NamespaceNotation() { Name = type.Namespace }; var @class = new ClassNotation() { Accessibility = type.Accessibility, Name = $"Proxy{type.Name}{RandomUtils.NewName()}" }; @class.CustomAttributes.Add($"[Norns.Destiny.Attributes.Proxy(typeof({CreateImplementKey(type)}))]".ToNotation()); if (type.IsGenericType) { @class.TypeParameters.AddRange(type.TypeParameters.Select(i => i.ToNotation())); } @namespace.Members.Add(@class); @class.Inherits.Add(type.FullName.ToNotation()); var context = new ProxyGeneratorContext() { Symbol = type }; context.SetCurrentNamespaceNotation(@namespace); context.SetCurrentClassNotation(@class); foreach (var member in type.Members.Union(type.Interfaces.SelectMany(i => i.Members)).Distinct()) { switch (member) { case IMethodSymbolInfo method when !method.IsStatic && method.MethodKind != MethodKindInfo.PropertyGet && method.MethodKind != MethodKindInfo.PropertySet && (method.CanOverride() || (method.ContainingType.IsInterface && !method.IsAbstract)) && method.Name != "Finalize": @class.Members.Add(CreateProxyMethod(method, context)); break; case IMethodSymbolInfo method when !method.IsStatic && method.MethodKind == MethodKindInfo.Constructor: @class.Members.Add(GenerateImplementConstructor(method, @class.Name)); break; case IPropertySymbolInfo property when property.CanOverride(): @class.Members.Add(CreateProxyProperty(property, context)); break; default: break; } } AddProxyInfo(@class, context, type); return(@namespace); }
private INotation GenerateImplementProperty(IPropertySymbolInfo property, ProxyGeneratorContext typeContext) { var context = new ProxyGeneratorContext() { Parent = typeContext, Symbol = property }; PropertyNotation notation; if (property.IsIndexer) { var indexer = new IndexerPropertyNotation(); indexer.Parameters.AddRange(property.Parameters.Select(i => new ParameterNotation() { Type = i.Type.FullName, Name = i.Name })); notation = indexer; } else { notation = new PropertyNotation(); } notation.IsOverride = !property.ContainingType.IsInterface && property.CanOverride(); notation.Accessibility = property.Accessibility; notation.Name = property.Name; notation.Type = property.Type.FullName; if (property.CanRead) { context.SetCurrentPropertyMethod(property.GetMethod); var getter = PropertyMethodNotation.Create(true); getter.Accessibility = property.GetMethod.Accessibility; var returnValueParameterName = context.GetReturnValueParameterName(); getter.Body.AddRange(Notation.Create("var ", returnValueParameterName, " = default(", property.Type.FullName, ");")); getter.Body.AddRange(Notation.Create("return ", returnValueParameterName, ";")); notation.Accessers.Add(getter); } if (property.CanWrite) { context.SetCurrentPropertyMethod(property.SetMethod); var setter = PropertyMethodNotation.Create(false); setter.Accessibility = property.SetMethod.Accessibility; setter.Body.Add(ConstNotations.Blank); notation.Accessers.Add(setter); } return(notation); }
public override INotation CreateImplement(ITypeSymbolInfo type) { var context = new ProxyGeneratorContext() { Symbol = type }; var @namespace = new NamespaceNotation() { Name = type.Namespace }; var @class = new ClassNotation() { Accessibility = type.Accessibility, Name = $"DefaultImplement{type.Name}{RandomUtils.NewName()}" }; @class.CustomAttributes.Add($"[Norns.Destiny.Attributes.DefaultImplement(typeof({CreateImplementKey(type)}))]".ToNotation()); if (type.IsGenericType) { @class.TypeParameters.AddRange(type.TypeParameters.Select(i => i.ToNotation())); } @namespace.Members.Add(@class); @class.Inherits.Add(type.FullName.ToNotation()); foreach (var member in type.Members.Union(type.Interfaces.SelectMany(i => i.Members)).Distinct(new FullNameSymbolInfoEqualityComparer())) { switch (member) { case IMethodSymbolInfo method when method.Accessibility != AccessibilityInfo.Private && !method.IsStatic && method.IsAbstract && method.MethodKind == MethodKindInfo.Method: @class.Members.Add(GenerateImplementMethod(method, context)); break; case IMethodSymbolInfo method when method.Accessibility != AccessibilityInfo.Private && !method.IsStatic && method.MethodKind == MethodKindInfo.Constructor: @class.Members.Add(GenerateImplementConstructor(method, @class.Name)); break; case IPropertySymbolInfo property when property.Accessibility != AccessibilityInfo.Private && !property.IsStatic: @class.Members.Add(GenerateImplementProperty(property, context)); break; default: break; } } return(@namespace); }
private INotation CreateProxyMethod(IMethodSymbolInfo method, ProxyGeneratorContext typeContext) { var context = new ProxyGeneratorContext() { Parent = typeContext, Symbol = method }; var notation = method.ToNotationDefinition(); context.SetCurrentMethodNotation(notation); var isInterface = method.ContainingType.IsInterface; notation.IsOverride = !isInterface && method.CanOverride(); var returnValueParameterName = context.GetReturnValueParameterName(); if (method.HasReturnValue) { notation.Body.AddRange(Notation.Create("var ", returnValueParameterName, " = default(", method.IsAsync ? method.ReturnType.TypeArguments.First().FullName : method.ReturnType.FullName, ");")); } notation.Body.Add(method.Parameters.Where(i => i.RefKind == RefKindInfo.Out).Select(i => $"{i.Name} = default;".ToNotation()).Combine()); notation.Body.AddRange(interceptors.SelectMany(i => i.BeforeMethod(context))); if (isInterface || (!method.IsAbstract && (method.Accessibility == AccessibilityInfo.Internal || method.Accessibility == AccessibilityInfo.Public))) { if (method.HasReturnValue) { notation.Body.AddRange(Notation.Create(returnValueParameterName, " = ")); } notation.Body.AddRange(Notation.Create(method.IsAsync ? "await " : string.Empty, method.ContainingType.IsInterface && !method.IsAbstract ? $"({context.GetProxyFieldName()} as {method.ContainingType.FullName})" : context.GetProxyFieldName(), ".", method.Name)); notation.Body.Add(ConstNotations.OpenParen); notation.Body.Add(notation.Parameters.ToCallParameters()); notation.Body.Add(ConstNotations.CloseParen); notation.Body.Add(ConstNotations.Semicolon); } notation.Body.AddRange(interceptors.SelectMany(i => i.AfterMethod(context))); if (method.HasReturnValue) { notation.Body.AddRange(Notation.Create("return ", returnValueParameterName, ";")); } return(notation); }
private INotation GenerateImplementMethod(IMethodSymbolInfo method, ProxyGeneratorContext typeContext) { var context = new ProxyGeneratorContext() { Parent = typeContext, Symbol = method }; var notation = method.ToNotationDefinition(); context.SetCurrentMethodNotation(notation); notation.IsOverride = !method.ContainingType.IsInterface && method.CanOverride(); notation.Body.Add(method.Parameters.Where(i => i.RefKind == RefKindInfo.Out).Select(i => $"{i.Name} = default;".ToNotation()).Combine()); var returnValueParameterName = context.GetReturnValueParameterName(); if (method.HasReturnValue) { notation.Body.AddRange(Notation.Create("var ", returnValueParameterName, " = default(", method.IsAsync ? method.ReturnType.TypeArguments.First().FullName : method.ReturnType.FullName, ");")); } if (method.HasReturnValue) { notation.Body.AddRange(Notation.Create("return ", returnValueParameterName, ";")); } return(notation); }
private INotation CreateProxyProperty(IPropertySymbolInfo property, ProxyGeneratorContext typeContext) { var context = new ProxyGeneratorContext() { Parent = typeContext, Symbol = property }; PropertyNotation notation; List <INotation> callName = new List <INotation>(); if (property.IsIndexer) { var indexer = new IndexerPropertyNotation(); indexer.Parameters.AddRange(property.Parameters.Select(i => new ParameterNotation() { Type = i.Type.FullName, Name = i.Name })); notation = indexer; callName.Add(ConstNotations.OpenBracket); callName.Add(indexer.Parameters.ToCallParameters()); callName.Add(ConstNotations.CloseBracket); } else { callName.Add(ConstNotations.Dot); callName.Add(property.Name.ToNotation()); notation = new PropertyNotation(); } var isInterface = property.ContainingType.IsInterface; notation.IsOverride = !isInterface && property.CanOverride(); notation.Accessibility = property.Accessibility; notation.Name = property.Name; notation.Type = property.Type.FullName; if (property.CanRead) { context.SetCurrentPropertyMethod(property.GetMethod); var getter = PropertyMethodNotation.Create(true); getter.Accessibility = property.GetMethod.Accessibility; var returnValueParameterName = context.GetReturnValueParameterName(); getter.Body.AddRange(Notation.Create("var ", returnValueParameterName, " = default(", property.Type.FullName, ");")); getter.Body.AddRange(interceptors.SelectMany(i => i.BeforeMethod(context))); if (isInterface || (getter.Accessibility == AccessibilityInfo.Public || getter.Accessibility == AccessibilityInfo.Internal)) { getter.Body.AddRange(Notation.Create(returnValueParameterName, " = ", context.GetProxyFieldName())); getter.Body.AddRange(callName); getter.Body.Add(ConstNotations.Semicolon); } getter.Body.AddRange(interceptors.SelectMany(i => i.AfterMethod(context))); getter.Body.AddRange(Notation.Create("return ", returnValueParameterName, ";")); notation.Accessers.Add(getter); } if (property.CanWrite) { context.SetCurrentPropertyMethod(property.SetMethod); var setter = PropertyMethodNotation.Create(false); setter.Accessibility = property.SetMethod.Accessibility; var returnValueParameterName = context.GetReturnValueParameterName(); setter.Body.AddRange(Notation.Create("var ", returnValueParameterName, " = value;")); setter.Body.AddRange(interceptors.SelectMany(i => i.BeforeMethod(context))); if (isInterface || (setter.Accessibility == AccessibilityInfo.Public || setter.Accessibility == AccessibilityInfo.Internal)) { setter.Body.Add(context.GetProxyFieldName().ToNotation()); setter.Body.AddRange(callName); setter.Body.AddRange(Notation.Create(" = ", returnValueParameterName, ";")); } setter.Body.AddRange(interceptors.SelectMany(i => i.AfterMethod(context))); notation.Accessers.Add(setter); } return(notation); }
public static MethodNotation GetCurrentMethodNotation(this ProxyGeneratorContext context) { return(context.TryGetValue(CurrentMethodNotation, out var data) ? data as MethodNotation : null); }
public static void SetCurrentMethodNotation(this ProxyGeneratorContext context, MethodNotation method) { context[CurrentMethodNotation] = method; }
public static void SetCurrentClassNotation(this ProxyGeneratorContext context, ClassNotation @class) { context[CurrentClassNotation] = @class; }
public static NamespaceNotation GetCurrentNamespaceNotation(this ProxyGeneratorContext context) { return(context.TryGetValue(CurrentNamespaceNotation, out var data) ? data as NamespaceNotation : null); }
public static void SetCurrentNamespaceNotation(this ProxyGeneratorContext context, NamespaceNotation @namespace) { context[CurrentNamespaceNotation] = @namespace; }
public static IMethodSymbolInfo GetCurrentPropertyMethod(this ProxyGeneratorContext context) { return(context.TryGetValue(CurrentPropertyMethod, out var data) ? data as IMethodSymbolInfo : null); }
public static void SetCurrentPropertyMethod(this ProxyGeneratorContext context, IMethodSymbolInfo method) { context[CurrentPropertyMethod] = method; }