private string GenerateCore(CodeGenerationContext context, Type @interface, Type implementationType, MethodInfo[] interfaceMethods, MethodInfo[] targetMethods, string targetTypeName) { var proxyClassName = GetInterceptableProxyClassName(implementationType, out var constraints); context.References.Add(@interface.Assembly); context.References.Add(implementationType.Assembly); var interceptableMethods = targetMethods.Where(it => _methodInvokerBuilder.CanIntercept(implementationType, it)).ToArray(); var isDisposable = typeof(IDisposable).IsAssignableFrom(implementationType); var isAsyncDisposable = typeof(IAsyncDisposable).IsAssignableFrom(implementationType); var disposableInterfaces = ""; if (isAsyncDisposable && isAsyncDisposable) { disposableInterfaces = " , IDisposable, IAsyncDisposable"; } else if (isAsyncDisposable) { disposableInterfaces = " , IDisposable"; } else if (isAsyncDisposable) { disposableInterfaces = " , IAsyncDisposable"; } context.WriteLines($"public class {proxyClassName} : {@interface.GetOutputName()}, IInterfaceProxy {disposableInterfaces}"); if (constraints is not null) { using (context.Indent()) { foreach (var constraint in constraints) { context.WriteLines(constraint); } } } using (context.CodeBlock()) { //Fields GenerateFields(context, implementationType, @interface, interceptableMethods, out var methodInfoAccessorFieldNames, out var invokerAccessorFieldNames, out var invokerMethodNames); //InvocationContextClasses. var invocationContextClassNames = new Dictionary <MethodInfo, string>(); foreach (var method in interceptableMethods) { var className = ResolveInvocationContextClassName(method); invocationContextClassNames[method] = GenerateInvocationContextClass(context, className, method); } //Constructor var constructorName = proxyClassName; if (implementationType.IsGenericTypeDefinition) { var index = constructorName.IndexOf('<'); constructorName = proxyClassName[..index];
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];