castleproject / Core

Castle Core, including Castle DynamicProxy, Logging Services and DictionaryAdapter
http://www.castleproject.org/
Other
2.2k stars 468 forks source link

Proxy of proxy using mixins #608

Closed amoraller closed 2 years ago

amoraller commented 2 years ago

Hi.

Why i can not create proxy of proxy using mixins?


    public interface I_Foo { }
    public class T_Foo : I_Foo { }
    public interface I_Bar { }
    public class T_Bar : I_Bar { } 

    public static class ProxyCreator() {

        static readonly ProxyGenerator pg = new ProxyGenerator();
        public static object Create()
        {
            var obj = new object();
            var proxy1 = Add_Foo(obj);
            var proxy2 = Add_Bar(proxy1);
            return proxy2;
        }
        public static object Add_Foo(object source)
        {
            ProxyGenerationOptions options = new();
            options.AddMixinInstance(source);
            options.AddMixinInstance(new T_Foo());
            return pg.CreateClassProxy<object>(options);
        }
        public static object Add_Bar(object source)
        {
            ProxyGenerationOptions options = new();
            options.AddMixinInstance(source);
            options.AddMixinInstance(new T_Bar());
            return pg.CreateClassProxy<object>(options);
        }
    }  

If i create second proxy i catch exeption

System.ArgumentException: "An item with the same key has already been added. Key: Castle.DynamicProxy.IProxyTargetAccessor"

image

jonorossi commented 2 years ago

@amoraller Can you please describe your scenario, proxying a proxy is not something I'd recommend.

amoraller commented 2 years ago

@jonorossi i want add interface and implementation for existing object at runtime. I have data source with IObservable<byte[]> implementation and i need create plugins for my app. Any plugin can modify behavior (with interceptor) or add interface implementation.

For example my usb device produced byte[] data, and plugins inspect specific data and send answer to device. User can enable plugin at runtime.

Sometime i use this code

public static IPrizrakDevice CreateDecorator(IPrizrakDevice @internal)
        {
            var stateSaver = new QueuePrizrakDeviceImpl(@internal);
            var options = new ProxyGenerationOptions();
            options.AddMixinInstance(stateSaver);
            Type[] interfaces = ProxyHelper.GetInterfaces(@internal);
            var proxy = pg.CreateInterfaceProxyWithTargetInterface(typeof(IPrizrakDevice), interfaces, @internal, options);
            return proxy as IPrizrakDevice;
        }

     public static Type[] GetInterfaces(object source)
        {
            IEnumerable<Type> interfaces = source.GetType().GetInterfaces();
            if (ProxyUtil.IsProxy(source))
            {
                interfaces = interfaces.Where(p => p != typeof(IProxyTargetAccessor));
            }
            return interfaces.ToArray();
        }

As a workaround i want use Fluent Builder pattern or use Dictionary with behaviour extensions.