Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retire ProxyGenerationException & introduce DynamicProxyException for internal faults #528

Merged
merged 11 commits into from
Jun 29, 2020
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Deprecations:
- `Castle.Core.Internal.PermissionUtil.IsGranted` (method)
- all type members in `Castle.DynamicProxy.ModuleScope` that gave direct access to DynamicProxy's type cache and `ModuleBuilder`s. Only `SaveAssembly`, `LoadAssemblyIntoCache`, and members supporting these two facilities are left public.
- almost all types and type members in the `Castle.DynamicProxy.*` sub-namespaces, as most of them are intended for internal use only.
- DynamicProxy's custom exception types have been replaced by standard BCL exceptions (where appropriate), and by a single `DynamicProxyException` type for internal DynamicProxy errors.

## 4.4.1 (2020-05-06)

Expand Down
3 changes: 2 additions & 1 deletion ref/Castle.Core-net45.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2516,6 +2516,8 @@ public class DefaultProxyBuilder : Castle.DynamicProxy.IProxyBuilder
public System.Type CreateInterfaceProxyTypeWithTargetInterface(System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, Castle.DynamicProxy.ProxyGenerationOptions options) { }
public System.Type CreateInterfaceProxyTypeWithoutTarget(System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, Castle.DynamicProxy.ProxyGenerationOptions options) { }
}
[System.Serializable]
public sealed class DynamicProxyException : System.Exception { }
public interface IChangeProxyTarget
{
void ChangeInvocationTarget(object target);
Expand Down Expand Up @@ -2661,7 +2663,6 @@ public class PersistentProxyBuilder : Castle.DynamicProxy.DefaultProxyBuilder
public PersistentProxyBuilder() { }
public string SaveAssembly() { }
}
public class ProxyGenerationException : System.Exception { }
[System.Serializable]
public class ProxyGenerationOptions : System.Runtime.Serialization.ISerializable
{
Expand Down
3 changes: 2 additions & 1 deletion ref/Castle.Core-netstandard2.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2482,6 +2482,8 @@ public class DefaultProxyBuilder : Castle.DynamicProxy.IProxyBuilder
public System.Type CreateInterfaceProxyTypeWithTargetInterface(System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, Castle.DynamicProxy.ProxyGenerationOptions options) { }
public System.Type CreateInterfaceProxyTypeWithoutTarget(System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, Castle.DynamicProxy.ProxyGenerationOptions options) { }
}
[System.Serializable]
public sealed class DynamicProxyException : System.Exception { }
public interface IChangeProxyTarget
{
void ChangeInvocationTarget(object target);
Expand Down Expand Up @@ -2617,7 +2619,6 @@ public class ModuleScope
public string WeakNamedModuleName { get; }
public static byte[] GetKeyPair() { }
}
public class ProxyGenerationException : System.Exception { }
public class ProxyGenerationOptions
{
public static readonly Castle.DynamicProxy.ProxyGenerationOptions Default;
Expand Down
3 changes: 2 additions & 1 deletion ref/Castle.Core-netstandard2.1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2482,6 +2482,8 @@ public class DefaultProxyBuilder : Castle.DynamicProxy.IProxyBuilder
public System.Type CreateInterfaceProxyTypeWithTargetInterface(System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, Castle.DynamicProxy.ProxyGenerationOptions options) { }
public System.Type CreateInterfaceProxyTypeWithoutTarget(System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, Castle.DynamicProxy.ProxyGenerationOptions options) { }
}
[System.Serializable]
public sealed class DynamicProxyException : System.Exception { }
public interface IChangeProxyTarget
{
void ChangeInvocationTarget(object target);
Expand Down Expand Up @@ -2617,7 +2619,6 @@ public class ModuleScope
public string WeakNamedModuleName { get; }
public static byte[] GetKeyPair() { }
}
public class ProxyGenerationException : System.Exception { }
public class ProxyGenerationOptions
{
public static readonly Castle.DynamicProxy.ProxyGenerationOptions Default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private ProxyGenerationOptions MixIn(object mixin)
[Test]
public void ClassProxy_AdditionalInterfaces()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateClassProxy(typeof(object), new[] { typeof(IProxyTargetAccessor) }));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}
Expand All @@ -50,7 +50,7 @@ public void ClassProxy_base()
[Test]
public void ClassProxy_Mixin()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateClassProxy(typeof(object), MixIn(new ImplementsProxyTargetAccessor())));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}
Expand All @@ -60,15 +60,15 @@ public void ClassProxy_Mixin()
[Test]
public void InterfaceProxyWithoutTarget_AdditionalInterfaces()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithoutTarget(typeof(IOne), new[] { typeof(IProxyTargetAccessor) }));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}

[Test]
public void InterfaceProxyWithoutTarget_Mixin()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithoutTarget(typeof(IOne), new[] { typeof(IProxyTargetAccessor) },
MixIn(new ImplementsProxyTargetAccessor())));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
Expand All @@ -77,31 +77,31 @@ public void InterfaceProxyWithoutTarget_Mixin()
[Test]
public void InterfaceProxyWithoutTarget_TargetInterface()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithoutTarget(typeof(IProxyTargetAccessor)));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}

[Test]
public void InterfaceProxyWithoutTarget_TargetInterface_derived()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithoutTarget(typeof(IProxyTargetAccessorDerived)));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}

[Test]
public void InterfaceProxyWithTarget_AdditionalInterfaces()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithTarget(typeof(IOne), new[] { typeof(IProxyTargetAccessor) }, new One()));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}

[Test]
public void InterfaceProxyWithTarget_Mixin()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithTarget(typeof(IOne), new[] { typeof(IProxyTargetAccessor) }, new One(),
MixIn(new ImplementsProxyTargetAccessor())));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
Expand All @@ -110,15 +110,15 @@ public void InterfaceProxyWithTarget_Mixin()
[Test]
public void InterfaceProxyWithTarget_Target()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithTarget(typeof(IProxyTargetAccessor), new ImplementsProxyTargetAccessor()));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}

[Test]
public void InterfaceProxyWithTarget_Target_derived()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithTarget(typeof(IProxyTargetAccessorDerived), new ImplementsProxyTargetAccessorDerived()));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}
Expand All @@ -128,15 +128,15 @@ public void InterfaceProxyWithTarget_Target_derived()
[Test]
public void InterfaceProxyWithTargetInterface_AdditionalInterfaces()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithTargetInterface(typeof(IOne), new[] { typeof(IProxyTargetAccessor) }, new One()));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}

[Test]
public void InterfaceProxyWithTargetInterface_Mixin()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithTargetInterface(typeof(IOne), new[] { typeof(IProxyTargetAccessor) }, new One(),
MixIn(new ImplementsProxyTargetAccessor())));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
Expand All @@ -145,15 +145,15 @@ public void InterfaceProxyWithTargetInterface_Mixin()
[Test]
public void InterfaceProxyWithTargetInterface_Target()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithTargetInterface(typeof(IProxyTargetAccessor), new ImplementsProxyTargetAccessor()));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
}

[Test]
public void InterfaceProxyWithTargetInterface_Target_derived()
{
var ex = Assert.Throws(typeof(ProxyGenerationException), () =>
var ex = Assert.Throws<InvalidOperationException>(() =>
generator.CreateInterfaceProxyWithTargetInterface(typeof(IProxyTargetAccessorDerived),
new ImplementsProxyTargetAccessorDerived()));
StringAssert.Contains("IProxyTargetAccessor", ex.Message);
Expand Down
39 changes: 39 additions & 0 deletions src/Castle.Core/DynamicProxy/DynamicProxyException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2004-2020 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Castle.DynamicProxy
{
using System;
using System.Runtime.Serialization;

// NOTE TO MAINTAINERS:
// Prefer throwing Base Class Library exception types wherever appropriate.
// This exception type is to be used mostly when something inside DynamicProxy goes wrong.
// Think of it as a "failed assertion" / "bug" exception.
[Serializable]
public sealed class DynamicProxyException : Exception
{
internal DynamicProxyException(string message) : base(message)
{
}

internal DynamicProxyException(string message, Exception innerException) : base(message, innerException)
{
}

internal DynamicProxyException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}
7 changes: 5 additions & 2 deletions src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ protected void GenerateParameterlessConstructor(ClassEmitter emitter, Type baseC
constructor.CodeBuilder.AddStatement(new AssignStatement(interceptorField,
new NewArrayExpression(1, typeof(IInterceptor))));
constructor.CodeBuilder.AddStatement(
new AssignArrayStatement(interceptorField, 0, new NewInstanceExpression(typeof(StandardInterceptor), new Type[0])));
new AssignArrayStatement(interceptorField, 0, new NewInstanceExpression(typeof(StandardInterceptor))));

// Invoke base constructor

Expand All @@ -339,6 +339,7 @@ protected ConstructorEmitter GenerateStaticConstructor(ClassEmitter emitter)
string.Format(
"Target type for the proxy implements {0} which is a DynamicProxy infrastructure interface and you should never implement it yourself. Are you trying to proxy an existing proxy?",
interfaceName);
throw new InvalidOperationException("This is a DynamicProxy2 error: " + message);
}
else if (ProxyGenerationOptions.MixinData.ContainsMixin(typeof(IProxyTargetAccessor)))
{
Expand All @@ -347,21 +348,23 @@ protected ConstructorEmitter GenerateStaticConstructor(ClassEmitter emitter)
string.Format(
"Mixin type {0} implements {1} which is a DynamicProxy infrastructure interface and you should never implement it yourself. Are you trying to mix in an existing proxy?",
mixinType.Name, interfaceName);
throw new InvalidOperationException("This is a DynamicProxy2 error: " + message);
}
else if (additionalInterfaces.Contains(typeof(IProxyTargetAccessor)))
{
message =
string.Format(
"You passed {0} as one of additional interfaces to proxy which is a DynamicProxy infrastructure interface and is implemented by every proxy anyway. Please remove it from the list of additional interfaces to proxy.",
interfaceName);
throw new InvalidOperationException("This is a DynamicProxy2 error: " + message);
}
else
{
// this can technically never happen
message = string.Format("It looks like we have a bug with regards to how we handle {0}. Please report it.",
interfaceName);
throw new DynamicProxyException(message);
}
throw new ProxyGenerationException("This is a DynamicProxy2 error: " + message);
}

protected void InitializeStaticFields(Type builtType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public void CopyGenericParametersFromMethod(MethodInfo methodToCopyGenericsFrom)
// big sanity check
if (genericTypeParams != null)
{
throw new ProxyGenerationException("CopyGenericParametersFromMethod: cannot invoke me twice");
throw new InvalidOperationException("Cannot invoke me twice");
}

SetGenericTypeParameters(GenericUtil.CopyGenericArguments(methodToCopyGenericsFrom, typebuilder, name2GenericType));
Expand Down Expand Up @@ -316,36 +316,7 @@ public void SetGenericTypeParameters(GenericTypeParameterBuilder[] genericTypePa

protected Type CreateType(TypeBuilder type)
{
try
{
return type.CreateTypeInfo();
}
catch (BadImageFormatException ex)
{
if (Debugger.IsAttached == false)
{
throw;
}

if (ex.Message.Contains(@"HRESULT: 0x8007000B") == false)
{
throw;
}

if (type.IsGenericTypeDefinition == false)
{
throw;
}

var message =
"This is a DynamicProxy2 error: It looks like you encountered a bug in Visual Studio debugger, " +
"which causes this exception when proxying types with generic methods having constraints on their generic arguments." +
"This code will work just fine without the debugger attached. " +
"If you wish to use debugger you may have to switch to Visual Studio 2010 where this bug was fixed.";
var exception = new ProxyGenerationException(message);
exception.Data.Add("ProxyType", type.ToString());
throw exception;
}
return type.CreateTypeInfo();
}

protected virtual void EnsureBuildersAreInAValidState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public override void LoadReference(ILGenerator gen)
{
if (Position == -1)
{
throw new ProxyGenerationException("ArgumentReference uninitialized");
throw new InvalidOperationException("ArgumentReference uninitialized");
}
switch (Position)
{
Expand All @@ -70,7 +70,7 @@ public override void StoreReference(ILGenerator gen)
{
if (Position == -1)
{
throw new ProxyGenerationException("ArgumentReference uninitialized");
throw new InvalidOperationException("ArgumentReference uninitialized");
}
gen.Emit(OpCodes.Starg, Position);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ internal class ConstReference : TypeReference
public ConstReference(object value)
: base(value.GetType())
{
if (!value.GetType().IsPrimitive && !(value is String))
{
throw new ProxyGenerationException("Invalid type to ConstReference");
}
Debug.Assert(value.GetType().IsPrimitive || value is string, "Invalid type to ConstReference");

this.value = value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public override void Emit(IMemberEmitter member, ILGenerator gen)
}
else
{
throw new ProxyGenerationException("Can't emit default value for type " + type);
throw new NotImplementedException("Can't emit default value for type " + type);
}
}

Expand All @@ -66,7 +66,7 @@ private void EmitByRef(ILGenerator gen)
}
else
{
throw new ProxyGenerationException("Can't emit default value for reference of type " + elementType);
throw new NotImplementedException("Can't emit default value for reference of type " + elementType);
}
}

Expand Down
Loading