AbstractInvocation
using Castle.DynamicProxy.Serialization;
using System;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security;
namespace Castle.DynamicProxy
{
[Serializable]
public abstract class AbstractInvocation : IInvocation, ISerializable
{
private readonly IInterceptor[] interceptors;
private readonly object[] arguments;
private int currentInterceptorIndex = -1;
private Type[] genericMethodArguments;
private readonly MethodInfo proxiedMethod;
protected readonly object proxyObject;
public abstract object InvocationTarget { get; }
public abstract Type TargetType { get; }
public abstract MethodInfo MethodInvocationTarget { get; }
public Type[] GenericArguments => genericMethodArguments;
public object Proxy => proxyObject;
public MethodInfo Method => proxiedMethod;
public object ReturnValue { get; set; }
public object[] Arguments => arguments;
protected AbstractInvocation(object proxy, IInterceptor[] interceptors, MethodInfo proxiedMethod, object[] arguments)
{
proxyObject = proxy;
this.interceptors = interceptors;
this.proxiedMethod = proxiedMethod;
this.arguments = arguments;
}
protected AbstractInvocation(object proxy, Type targetType, IInterceptor[] interceptors, MethodInfo proxiedMethod, object[] arguments, IInterceptorSelector selector, ref IInterceptor[] methodInterceptors)
: this(proxy, interceptors, proxiedMethod, arguments)
{
methodInterceptors = SelectMethodInterceptors(selector, methodInterceptors, targetType);
this.interceptors = methodInterceptors;
}
private IInterceptor[] SelectMethodInterceptors(IInterceptorSelector selector, IInterceptor[] methodInterceptors, Type targetType)
{
return methodInterceptors ?? selector.SelectInterceptors(targetType, Method, interceptors) ?? new IInterceptor[0];
}
public void SetGenericMethodArguments(Type[] arguments)
{
genericMethodArguments = arguments;
}
public MethodInfo GetConcreteMethod()
{
return EnsureClosedMethod(Method);
}
public MethodInfo GetConcreteMethodInvocationTarget()
{ get; }
public void SetArgumentValue(int index, object value)
{
arguments[index] = value;
}
public object GetArgumentValue(int index)
{
return arguments[index];
}
public void Proceed()
{
if (interceptors == null)
InvokeMethodOnTarget();
else {
currentInterceptorIndex++;
try {
if (currentInterceptorIndex == interceptors.Length)
InvokeMethodOnTarget();
else {
if (currentInterceptorIndex > interceptors.Length) {
string text = (interceptors.Length <= 1) ? " interceptor" : (" each one of " + interceptors.Length + " interceptors");
string message = "This is a DynamicProxy2 error: invocation.Proceed() has been called more times than expected.This usually signifies a bug in the calling code. Make sure that" + text + " selected for the method '" + Method + "'calls invocation.Proceed() at most once.";
throw new InvalidOperationException(message);
}
interceptors[currentInterceptorIndex].Intercept(this);
}
} finally {
currentInterceptorIndex--;
}
}
}
[SecurityCritical]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.SetType(typeof(RemotableInvocation));
info.AddValue("invocation", new RemotableInvocation(this));
}
protected abstract void InvokeMethodOnTarget();
protected void ThrowOnNoTarget()
{
string text = (interceptors.Length != 0) ? "The interceptor attempted to 'Proceed'" : "There are no interceptors specified";
string text2;
string text3;
if (Method.DeclaringType.IsClass && Method.IsAbstract) {
text2 = "is abstract";
text3 = "an abstract method";
} else {
text2 = "has no target";
text3 = "method without target";
}
string message = $"""{text}""{Method}""{text2}""{text3}""";
throw new NotImplementedException(message);
}
private MethodInfo EnsureClosedMethod(MethodInfo method)
{
if (method.ContainsGenericParameters)
return method.GetGenericMethodDefinition().MakeGenericMethod(genericMethodArguments);
return method;
}
}
}