ComponentProxyInspector
Inspects the component configuration and type looking for information
that can influence the generation of a proxy for that component.
We specifically look for additionalInterfaces and marshalByRefProxy on the component configuration or the ComponentProxyBehaviorAttribute attribute.
using Castle.Core;
using Castle.Core.Configuration;
using Castle.Core.Internal;
using Castle.MicroKernel.Proxy;
using Castle.MicroKernel.SubSystems.Conversion;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
namespace Castle.MicroKernel.ModelBuilder.Inspectors
{
[Serializable]
public class ComponentProxyInspector : IContributeComponentModelConstruction
{
private readonly IConversionManager converter;
public ComponentProxyInspector(IConversionManager converter)
{
this.converter = converter;
}
public virtual void ProcessModel(IKernel kernel, ComponentModel model)
{
ReadProxyBehavior(kernel, model);
}
protected virtual ComponentProxyBehaviorAttribute ReadProxyBehaviorFromType(Type implementation)
{
return implementation.GetAttributes<ComponentProxyBehaviorAttribute>().FirstOrDefault();
}
protected virtual void ReadProxyBehavior(IKernel kernel, ComponentModel model)
{
ComponentProxyBehaviorAttribute componentProxyBehaviorAttribute = ReadProxyBehaviorFromType(model.Implementation);
if (componentProxyBehaviorAttribute == null)
componentProxyBehaviorAttribute = new ComponentProxyBehaviorAttribute();
ReadProxyBehaviorFromConfig(model, componentProxyBehaviorAttribute);
ApplyProxyBehavior(componentProxyBehaviorAttribute, model);
}
private void ReadProxyBehaviorFromConfig(ComponentModel model, ComponentProxyBehaviorAttribute behavior)
{
if ((object)model.Configuration != null) {
string text = ((NameValueCollection)model.Configuration.get_Attributes())["marshalByRefProxy"];
if (text != null)
behavior.UseMarshalByRefProxy = converter.PerformConversion<bool?>(text).GetValueOrDefault(false);
IConfiguration val = model.Configuration.get_Children().get_Item("additionalInterfaces");
if (val != null) {
List<Type> list = new List<Type>(behavior.AdditionalInterfaces);
foreach (IConfiguration item2 in (List<IConfiguration>)val.get_Children()) {
string value = ((NameValueCollection)item2.get_Attributes())["interface"];
Type item = converter.PerformConversion<Type>(value);
list.Add(item);
}
behavior.AdditionalInterfaces = list.ToArray();
}
}
}
private static void ApplyProxyBehavior(ComponentProxyBehaviorAttribute behavior, ComponentModel model)
{
ProxyOptions proxyOptions = model.ObtainProxyOptions(true);
if (behavior.UseMarshalByRefProxy)
EnsureComponentRegisteredWithInterface(model);
proxyOptions.UseMarshalByRefAsBaseClass = behavior.UseMarshalByRefProxy;
proxyOptions.AddAdditionalInterfaces(behavior.AdditionalInterfaces);
if (model.Implementation.IsInterface)
proxyOptions.OmitTarget = true;
}
private static void EnsureComponentRegisteredWithInterface(ComponentModel model)
{
if (model.HasClassServices) {
string message = $"""{model.Implementation.FullName}""{model.Services.First().FullName}""";
throw new ComponentRegistrationException(message);
}
}
}
}