public string Generate(CodeGenerationContext context, Type baseType, MethodInfo[] interceptableMethods) { context.References.Add(baseType.Assembly); var proxyClassName = GetInterceptableProxyClassName(baseType, out var constraints); context.WriteLines($"public sealed class {proxyClassName} : {baseType.GetOutputName()}, IVirtualMethodProxy"); #region Generic argument constraints. if (constraints is not null) { using (context.Indent()) { foreach (var constraint in constraints) { context.WriteLines(constraint); } } } #endregion using (context.CodeBlock()) { #region Fields GenerateFields(context, baseType, null, interceptableMethods, out var methodInfoAccessorFieldNames, out var invokerAccessorFieldNames, out var invokerMethodNames); context.WriteLines(); #endregion #region InvocationContextClasses. var invocationContextClassNames = new Dictionary <MethodInfo, string>(); foreach (var method in interceptableMethods) { var className = ResolveInvocationContextClassName(method); invocationContextClassNames[method] = GenerateInvocationContextClass(context, className, method); context.WriteLines(); } #endregion #region Properties var properties = baseType.GetProperties(); if (properties.Any()) { foreach (var property in properties) { string?getInvocationContextClassName = null; string?setInvocationContextClassName = null; string?getInvokerFieldName = null; string?setInvokerFieldName = null; string?getMethodAccessor = null; string?setMethodAccessor = null; var getMethod = property.GetMethod; var setMethod = property.SetMethod; if (getMethod != null) { if (methodInfoAccessorFieldNames.TryGetValue(getMethod, out var accessor)) { getMethodAccessor = $"{accessor}.Value"; } } if (setMethod != null) { if (methodInfoAccessorFieldNames.TryGetValue(setMethod, out var accessor)) { setMethodAccessor = $"{accessor}.Value"; } } if (getMethod != null) { invocationContextClassNames.TryGetValue(getMethod, out getInvocationContextClassName); invokerAccessorFieldNames?.TryGetValue(getMethod, out getInvokerFieldName); } if (setMethod != null) { invocationContextClassNames.TryGetValue(setMethod, out setInvocationContextClassName); invokerAccessorFieldNames?.TryGetValue(setMethod, out setInvokerFieldName); } if (!string.IsNullOrWhiteSpace(getInvocationContextClassName) || !string.IsNullOrWhiteSpace(setInvocationContextClassName)) { GenerateProperty(context, property, getInvocationContextClassName, setInvocationContextClassName, getMethodAccessor, setMethodAccessor, getInvokerFieldName, setInvokerFieldName, null); } } } #endregion #region Constructors var constructorName = proxyClassName; if (baseType.IsGenericTypeDefinition) { var index = constructorName.IndexOf('<'); constructorName = proxyClassName[..index];
public override bool TryGenerate(ServiceDescriptor serviceDescriptor, CodeGenerationContext codeGenerationContext, out string[]?proxyTypeNames) { proxyTypeNames = null; var @interface = serviceDescriptor.ServiceType; if ([email protected]) { return(false); } var implementationType = serviceDescriptor.ImplementationType; if (implementationType == null) { return(false); } Validate(implementationType); if ([email protected] && [email protected]) { return(false); } var methods = implementationType .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(it => it.IsPublic || it.IsFamily || it.IsFamilyAndAssembly) .Where(it => it.DeclaringType != typeof(object)) ; var interceptableMethods = methods.Where(it => _methodInvokerBuilder.CanIntercept(implementationType, it)); if (!interceptableMethods.Any()) { return(false); } foreach (var method in methods) { codeGenerationContext.References.Add(method.ReturnType.Assembly); foreach (var parameter in method.GetParameters()) { codeGenerationContext.References.Add(parameter.ParameterType.Assembly); } } MethodInfo[] interfaceMethods; MethodInfo[] targetMethods; if (@interface.IsGenericTypeDefinition && implementationType.IsGenericTypeDefinition) { GetGenericInterfaceMapping(@interface, implementationType, out interfaceMethods, out targetMethods); } else { var map = implementationType.GetInterfaceMap(@interface); interfaceMethods = map.InterfaceMethods; targetMethods = map.TargetMethods; } var nonInterfaceMethods = interceptableMethods.Except(targetMethods).Where(it => it.IsVirtual); string?virtualMethodClassName = null; if (nonInterfaceMethods.Any()) { virtualMethodClassName = _virtualMethodProxyGeneratorAccessor.Value.Generate(codeGenerationContext, implementationType, nonInterfaceMethods.ToArray()); } if (!interceptableMethods.Intersect(targetMethods).Any()) { proxyTypeNames = new string[] { virtualMethodClassName ! }; return(true); } var interfaceProxyName = GenerateCore(codeGenerationContext, @interface, implementationType, interfaceMethods, targetMethods, virtualMethodClassName ?? implementationType.GetOutputName()); proxyTypeNames = string.IsNullOrEmpty(virtualMethodClassName) ? new string[] { interfaceProxyName } : new string[] { interfaceProxyName, virtualMethodClassName }; return(true); }