public object Cast(IComponent component, Type targetType) { Guard.NotNull(() => component, component); Guard.NotNull(() => targetType, targetType); if (!targetType.IsInterface) throw new ArgumentException(Strings.SmartCast.InterfaceRequired); if (component.Schema == null) throw new ArgumentException(Strings.SmartCast.SchemaRequired(component)); var propertyName = "$" + targetType.AssemblyQualifiedName; // NOTE: we cache the proxy instance for performance. var proxyProperty = component.Properties.FirstOrDefault(p => p.Name == propertyName); if (proxyProperty == null) { var containerSchema = component.Schema as IContainerInfo; if (containerSchema != null) { if (!IsCompatibleContainer(containerSchema, targetType)) return null; } else if (!IsCompatibleComponent(component.Schema, targetType)) { return null; } proxyProperty = component.CreateProperty(propertyName); // Try to expose the most specific interface of the received component. var componentType = component is IProduct ? typeof(IProduct) : (component is IElement ? typeof(IElement) : (component is ICollection ? typeof(ICollection) : typeof(IComponent))); proxyProperty.Value = generator.CreateInterfaceProxyWithTarget( componentType, new[] { targetType }, component, new Interceptor(component, Behaviors.Default)); } return proxyProperty.Value; }