Skip to content

Commit

Permalink
Merge pull request #553 from stakx/dp/refactor/instance-contributors
Browse files Browse the repository at this point in the history
Split up instance contributors into 3 single-purpose contributors
  • Loading branch information
stakx committed Jan 5, 2021
2 parents eae5dc3 + 12f6964 commit 9143de2
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 143 deletions.
Expand Up @@ -12,66 +12,48 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#if FEATURE_SERIALIZATION

namespace Castle.DynamicProxy.Contributors
{
using System;
using System.Collections.Generic;
using System.Reflection;
#if FEATURE_SERIALIZATION
using System.Runtime.Serialization;
#endif

using Castle.DynamicProxy.Generators.Emitters;
using Castle.DynamicProxy.Generators.Emitters.CodeBuilders;
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
using Castle.DynamicProxy.Internal;
using Castle.DynamicProxy.Tokens;

internal class ClassProxyInstanceContributor : ProxyInstanceContributor
internal class ClassProxySerializableContributor : SerializableContributor
{
#if FEATURE_SERIALIZATION
private readonly bool delegateToBaseGetObjectData;
private readonly bool implementISerializable;
private ConstructorInfo serializationConstructor;
private readonly IList<FieldReference> serializedFields = new List<FieldReference>();
#endif

public ClassProxyInstanceContributor(Type targetType, IList<MethodInfo> methodsToSkip, Type[] interfaces,
public ClassProxySerializableContributor(Type targetType, IList<MethodInfo> methodsToSkip, Type[] interfaces,
string typeId)
: base(targetType, interfaces, typeId)
{
#if FEATURE_SERIALIZATION
if (targetType.IsSerializable)
{
implementISerializable = true;
delegateToBaseGetObjectData = VerifyIfBaseImplementsGetObjectData(targetType, methodsToSkip);
}
#endif
}

protected override Reference GetTargetReference(ClassEmitter emitter)
{
return SelfReference.Self;
}

public override void Generate(ClassEmitter @class)
{
var interceptors = @class.GetField("__interceptors");
#if FEATURE_SERIALIZATION
if (implementISerializable)
{
ImplementGetObjectData(@class);
Constructor(@class);
}
#endif
ImplementProxyTargetAccessor(@class, interceptors);
foreach (var attribute in targetType.GetNonInheritableAttributes())
{
@class.DefineCustomAttribute(attribute.Builder);
}
}

#if FEATURE_SERIALIZATION
protected override void AddAddValueInvocation(ArgumentReference serializationInfo, MethodEmitter getObjectData,
FieldReference field)
{
Expand Down Expand Up @@ -229,6 +211,7 @@ private bool VerifyIfBaseImplementsGetObjectData(Type baseType, IList<MethodInfo

return true;
}
#endif
}
}
}

#endif

This file was deleted.

Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#if FEATURE_SERIALIZATION

namespace Castle.DynamicProxy.Contributors
{
using System;
Expand All @@ -21,19 +23,13 @@ namespace Castle.DynamicProxy.Contributors
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
using Castle.DynamicProxy.Tokens;

internal class InterfaceProxyInstanceContributor : ProxyInstanceContributor
internal class InterfaceProxySerializableContributor : SerializableContributor
{
protected override Reference GetTargetReference(ClassEmitter emitter)
{
return emitter.GetField("__target");
}

public InterfaceProxyInstanceContributor(Type targetType, string proxyGeneratorId, Type[] interfaces)
public InterfaceProxySerializableContributor(Type targetType, string proxyGeneratorId, Type[] interfaces)
: base(targetType, interfaces, proxyGeneratorId)
{
}

#if FEATURE_SERIALIZATION
protected override void CustomizeGetObjectData(AbstractCodeBuilder codebuilder, ArgumentReference serializationInfo,
ArgumentReference streamingContext, ClassEmitter emitter)
{
Expand All @@ -52,6 +48,7 @@ public InterfaceProxyInstanceContributor(Type targetType, string proxyGeneratorI
new ConstReference(targetType.AssemblyQualifiedName).
ToExpression())));
}
#endif
}
}
}

#endif
@@ -0,0 +1,47 @@
// Copyright 2004-2021 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.Contributors
{
using System;

using Castle.DynamicProxy.Generators;
using Castle.DynamicProxy.Generators.Emitters;
using Castle.DynamicProxy.Internal;

/// <summary>
/// Reproduces the proxied type's non-inheritable custom attributes on the proxy type.
/// </summary>
internal sealed class NonInheritableAttributesContributor : ITypeContributor
{
private readonly Type targetType;

public NonInheritableAttributesContributor(Type targetType)
{
this.targetType = targetType;
}

public void Generate(ClassEmitter emitter)
{
foreach (var attribute in targetType.GetNonInheritableAttributes())
{
emitter.DefineCustomAttribute(attribute.Builder);
}
}

public void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model)
{
}
}
}
@@ -0,0 +1,74 @@
// Copyright 2004-2021 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.Contributors
{
using System;

using Castle.DynamicProxy.Generators;
using Castle.DynamicProxy.Generators.Emitters;
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;

/// <summary>
/// Adds an implementation for <see cref="IProxyTargetAccessor"/> to the proxy type.
/// </summary>
internal sealed class ProxyTargetAccessorContributor : ITypeContributor
{
private readonly Func<Reference> getTargetReference;
private readonly Type targetType;

public ProxyTargetAccessorContributor(Func<Reference> getTargetReference, Type targetType)
{
this.getTargetReference = getTargetReference;
this.targetType = targetType;
}

public void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model)
{
}

public void Generate(ClassEmitter emitter)
{
var interceptorsField = emitter.GetField("__interceptors");
var targetReference = getTargetReference();

var dynProxyGetTarget = emitter.CreateMethod(nameof(IProxyTargetAccessor.DynProxyGetTarget), typeof(object));

dynProxyGetTarget.CodeBuilder.AddStatement(
new ReturnStatement(new ConvertExpression(typeof(object), targetType, targetReference.ToExpression())));

var dynProxySetTarget = emitter.CreateMethod(nameof(IProxyTargetAccessor.DynProxySetTarget), typeof(void), typeof(object));

// we can only change the target of the interface proxy
if (targetReference is FieldReference targetField)
{
dynProxySetTarget.CodeBuilder.AddStatement(
new AssignStatement(targetField,
new ConvertExpression(targetField.Fieldbuilder.FieldType, dynProxySetTarget.Arguments[0].ToExpression())));
}
else
{
dynProxySetTarget.CodeBuilder.AddStatement(
new ThrowStatement(typeof(InvalidOperationException), "Cannot change the target of the class proxy."));
}

dynProxySetTarget.CodeBuilder.AddStatement(new ReturnStatement());

var getInterceptors = emitter.CreateMethod(nameof(IProxyTargetAccessor.GetInterceptors), typeof(IInterceptor[]));

getInterceptors.CodeBuilder.AddStatement(
new ReturnStatement(interceptorsField));
}
}
}
Expand Up @@ -12,89 +12,38 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#if FEATURE_SERIALIZATION

namespace Castle.DynamicProxy.Contributors
{
using System;
using System.Reflection;
#if FEATURE_SERIALIZATION
using System.Runtime.Serialization;
#endif

using Castle.DynamicProxy.Generators;
using Castle.DynamicProxy.Generators.Emitters;
using Castle.DynamicProxy.Generators.Emitters.CodeBuilders;
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
using Castle.DynamicProxy.Internal;
#if FEATURE_SERIALIZATION
using Castle.DynamicProxy.Serialization;
#endif
using Castle.DynamicProxy.Tokens;

internal abstract class ProxyInstanceContributor : ITypeContributor
internal abstract class SerializableContributor : ITypeContributor
{
protected readonly Type targetType;
private readonly string proxyTypeId;
private readonly Type[] interfaces;

protected ProxyInstanceContributor(Type targetType, Type[] interfaces, string proxyTypeId)
protected SerializableContributor(Type targetType, Type[] interfaces, string proxyTypeId)
{
this.targetType = targetType;
this.proxyTypeId = proxyTypeId;
this.interfaces = interfaces ?? Type.EmptyTypes;
}

protected abstract Reference GetTargetReference(ClassEmitter emitter);

private Expression GetTargetReferenceExpression(ClassEmitter emitter)
{
return GetTargetReference(emitter).ToExpression();
}

public virtual void Generate(ClassEmitter @class)
{
var interceptors = @class.GetField("__interceptors");
#if FEATURE_SERIALIZATION
ImplementGetObjectData(@class);
#endif
ImplementProxyTargetAccessor(@class, interceptors);
foreach (var attribute in targetType.GetNonInheritableAttributes())
{
@class.DefineCustomAttribute(attribute.Builder);
}
}

protected void ImplementProxyTargetAccessor(ClassEmitter emitter, FieldReference interceptorsField)
{
var dynProxyGetTarget = emitter.CreateMethod("DynProxyGetTarget", typeof(object));

dynProxyGetTarget.CodeBuilder.AddStatement(
new ReturnStatement(new ConvertExpression(typeof(object), targetType, GetTargetReferenceExpression(emitter))));

var dynProxySetTarget = emitter.CreateMethod("DynProxySetTarget", typeof(void), typeof(object));

// we can only change the target of the interface proxy
var targetField = GetTargetReference(emitter) as FieldReference;
if (targetField != null)
{
dynProxySetTarget.CodeBuilder.AddStatement(
new AssignStatement(targetField,
new ConvertExpression(targetField.Fieldbuilder.FieldType, dynProxySetTarget.Arguments[0].ToExpression())));
}
else
{
dynProxySetTarget.CodeBuilder.AddStatement(
new ThrowStatement(typeof(InvalidOperationException), "Cannot change the target of the class proxy."));
}

dynProxySetTarget.CodeBuilder.AddStatement(new ReturnStatement());

var getInterceptors = emitter.CreateMethod("GetInterceptors", typeof(IInterceptor[]));

getInterceptors.CodeBuilder.AddStatement(
new ReturnStatement(interceptorsField));
}

#if FEATURE_SERIALIZATION
protected void ImplementGetObjectData(ClassEmitter emitter)
{
var getObjectData = emitter.CreateMethod("GetObjectData", typeof(void),
Expand Down Expand Up @@ -200,10 +149,11 @@ protected void ImplementGetObjectData(ClassEmitter emitter)

protected abstract void CustomizeGetObjectData(AbstractCodeBuilder builder, ArgumentReference serializationInfo,
ArgumentReference streamingContext, ClassEmitter emitter);
#endif

public void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model)
{
}
}
}
}

#endif

0 comments on commit 9143de2

Please sign in to comment.