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.
Original file line number Diff line number Diff line change
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.

Original file line number Diff line number Diff line change
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 @@ protected override void CustomizeGetObjectData(AbstractCodeBuilder codebuilder,
new ConstReference(targetType.AssemblyQualifiedName).
ToExpression())));
}
#endif
}
}
}

#endif
Original file line number Diff line number Diff line change
@@ -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)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
Original file line number Diff line number Diff line change
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 virtual void AddAddValueInvocation(ArgumentReference serializationInfo

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

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

#endif
Loading

0 comments on commit 9143de2

Please sign in to comment.