Beispiel #1
0
        static object CreateStaticProxy(Type duck, Type @interface, MissingMethods missingMethods)
        {
            if (duck == null)
            {
                throw new ArgumentNullException(nameof(duck));
            }
            if (@interface == null)
            {
                throw new ArgumentNullException(nameof(@interface));
            }
            if ([email protected]().IsInterface)
            {
                throw new ArgumentException($"{@interface} is not an interface");
            }

            string assemblyName    = "Ducks_Static_" + @interface.AsmName() + "_" + duck.AsmName() + ".dll";
            var    assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run);
            var    moduleBuilder   = assemblyBuilder.DefineDynamicModule(assemblyName);

            TypeBuilder typeBuilder = moduleBuilder.DefineType("Proxy");

            foreach (var face in @interface.GetTypeInfo().GetInterfaces().Concat(@interface))
            {
                typeBuilder.AddInterfaceImplementation(face);
            }

            var ctor = typeBuilder.DefineDefaultConstructor(Public);

            foreach (var face in @interface.GetTypeInfo().GetInterfaces().Concat(@interface))
            {
                DefineMethods(typeBuilder, duck, face, missingMethods);
            }

            return(Activator.CreateInstance(typeBuilder.CreateTypeInfo().AsType()));
        }
Beispiel #2
0
 public TypePair(Type from, Type to, MissingMethods missingMethods)
 {
     if (from == null)
     {
         throw new ArgumentNullException(nameof(from));
     }
     if (to == null)
     {
         throw new ArgumentNullException(nameof(to));
     }
     From           = from;
     To             = to;
     MissingMethods = missingMethods;
 }
Beispiel #3
0
        /// <param name="duck">The duck</param>
        /// <param name="interface">the interface to cast <paramref name="duck"/></param>
        static Func <Delegate, object> CreateProxy(Type duck, Type @interface, MissingMethods missingMethods)
        {
            if (duck == null)
            {
                throw new ArgumentNullException(nameof(duck));
            }
            if (@interface == null)
            {
                throw new ArgumentNullException(nameof(@interface));
            }
            if ([email protected])
            {
                throw new ArgumentException($"{@interface} is not an interface");
            }

            string assemblyName    = "Ducks_Instance_" + @interface.AsmName() + "_" + duck.AsmName() + ".dll";
            var    assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run);
            var    moduleBuilder   = assemblyBuilder.DefineDynamicModule(assemblyName);

            TypeBuilder typeBuilder = moduleBuilder.DefineType("Proxy");

            foreach (var face in @interface.GetInterfaces().Concat(@interface, typeof(IDuck)))
            {
                typeBuilder.AddInterfaceImplementation(face);
            }

            var duckField = typeBuilder.DefineField("duck", duck, FieldAttributes.Private | FieldAttributes.InitOnly);

            var ctor = typeBuilder.DefineConstructor(duck, duckField);

            bool defined = false;

            foreach (var face in @interface.GetInterfaces().Concat(@interface))
            {
                DefineMembers(duck, face, typeBuilder, duckField, ref defined);
            }

            var create = typeBuilder.DefineStaticCreateMethod(duck, ctor, typeof(Delegate));

            typeBuilder.DefineUnwrapMethod(duckField);

            Type t = typeBuilder.CreateType();

            return((Func <Delegate, object>)Delegate.CreateDelegate(typeof(Func <Delegate, object>), t.GetMethod("Create", BindingFlags.Static | BindingFlags.Public)));
        }
Beispiel #4
0
        /// <param name="duck">The duck</param>
        /// <param name="interface">the interface to cast <paramref name="duck"/></param>
        /// <param name="missingMethods">How to handle missing methods</param>
        static IDuckDelegateFactory CreateProxy(Type duck, Type @interface, MissingMethods missingMethods)
        {
            if (duck == null)
            {
                throw new ArgumentNullException(nameof(duck));
            }
            if (@interface == null)
            {
                throw new ArgumentNullException(nameof(@interface));
            }
            if ([email protected]().IsInterface)
            {
                throw new ArgumentException($"{@interface} is not an interface");
            }

            string assemblyName    = "Ducks_Instance_" + @interface.AsmName() + "_" + duck.AsmName() + ".dll";
            var    assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run);
            var    moduleBuilder   = assemblyBuilder.DefineDynamicModule(assemblyName);

            TypeBuilder proxyBuilder = moduleBuilder.DefineType($"{duck.Name}_{@interface.Name}_DelegateProxy");

            foreach (var face in @interface.GetInterfaces().Concat(@interface, typeof(IDuck)))
            {
                proxyBuilder.AddInterfaceImplementation(face);
            }

            var duckField = proxyBuilder.DefineField("duck", duck, FieldAttributes.Private | FieldAttributes.InitOnly);

            var ctor = proxyBuilder.DefineConstructor(duck, duckField);

            bool defined = false;

            foreach (var face in @interface.GetInterfaces().Concat(@interface))
            {
                DefineMembers(duck, face, proxyBuilder, duckField, ref defined);
            }

            proxyBuilder.DefineUnwrapMethod(duckField);

            var factoryBuilder = CreateFactory(moduleBuilder, duck, ctor);

            proxyBuilder.CreateTypeInfo();
            return((IDuckDelegateFactory)Activator.CreateInstance(factoryBuilder.CreateTypeInfo().AsType()));
        }
Beispiel #5
0
        static void DefineMethods(TypeBuilder typeBuilder, Type duck, Type @interface, MissingMethods missingMethods)
        {
            foreach (var method in @interface.GetTypeInfo().GetMethods().Where(m => !m.IsSpecialName))
            {
                MethodInfo duckMethod = duck.FindDuckMethod(method, PublicStatic, missingMethods);
                AddMethod(typeBuilder, duckMethod, method);
            }

            foreach (var prop in @interface.GetTypeInfo().GetProperties())
            {
                var duckProp = duck.FindDuckProperty(prop, PublicStatic, missingMethods);
                AddProperty(typeBuilder, duckProp, prop);
            }

            foreach (var evt in @interface.GetTypeInfo().GetEvents())
            {
                var duckEvent = duck.FindDuckEvent(evt, PublicStatic, missingMethods);
                AddEvent(typeBuilder, duckEvent, evt);
            }
        }
Beispiel #6
0
 internal static object Cast(Type from, Type to, MissingMethods missingMethods)
 {
     return(proxies.GetOrAdd(new TypePair(from, to, missingMethods), pair => CreateStaticProxy(pair.From, pair.To, pair.MissingMethods)));
 }
Beispiel #7
0
        internal static object Cast(Delegate from, Type to, MissingMethods missingMethods)
        {
            var factory = casts.GetOrAdd(new TypePair(from.GetType(), to, missingMethods), pair => CreateProxy(pair.From, pair.To, pair.MissingMethods));

            return(factory.Create(from));
        }
Beispiel #8
0
        static void DefineMembers(Type duck, Type @interface, TypeBuilder typeBuilder, FieldBuilder duckField, MissingMethods missingMethods)
        {
            foreach (var method in @interface.GetTypeInfo().GetMethods().Where(mi => !mi.IsSpecialName)) // ignore get and set property methods
            {
                var duckMethod = duck.FindDuckMethod(method, PublicInstance, missingMethods);
                typeBuilder.AddMethod(duckMethod, method, duckField);
            }

            foreach (var prop in @interface.GetTypeInfo().GetProperties())
            {
                var duckProp = duck.FindDuckProperty(prop, PublicInstance, missingMethods);
                AddProperty(typeBuilder, duckProp, prop, duckField);
            }

            foreach (var evt in @interface.GetTypeInfo().GetEvents())
            {
                var duckEvent = duck.FindDuckEvent(evt, PublicInstance, missingMethods);
                AddEvent(typeBuilder, duckEvent, evt, duckField);
            }
        }
Beispiel #9
0
 public static EventInfo FindDuckEvent(this Type duck, EventInfo evt, BindingFlags bindingFlags, MissingMethods missingMethods)
 {
     try
     {
         var found = duck.GetEvent(evt.Name, bindingFlags);
         if (found == null && missingMethods == MissingMethods.NotImplemented)
         {
             return(null);
         }
         if (found == null)
         {
             throw new InvalidCastException($"Type {duck.Name} does not have a {bindingFlags} event {evt.Name}");
         }
         if (evt.EventHandlerType != found.EventHandlerType)
         {
             throw new InvalidCastException($"Type {duck.Name} {bindingFlags} event {evt.Name} has type {found.EventHandlerType.Name} but expected type {evt.EventHandlerType.Name}");
         }
         return(found);
     }
     catch (AmbiguousMatchException)
     {
         throw new InvalidCastException($"Type {duck.Name} has an ambiguous match for {bindingFlags} event {evt.Name}");
     }
 }
Beispiel #10
0
 public static PropertyInfo FindDuckProperty(this Type duck, PropertyInfo prop, BindingFlags bindingFlags, MissingMethods missingMethods)
 {
     try
     {
         var found = duck.GetProperty(prop.Name, bindingFlags, null, prop.PropertyType, prop.ParameterTypes(), null);
         if (found == null && missingMethods == MissingMethods.NotImplemented)
         {
             return(null);
         }
         if (found == null)
         {
             throw new InvalidCastException($"Type {duck.Name} does not have a {bindingFlags} property {prop.Name} or parameters types do not match");
         }
         if (prop.CanRead && !found.CanRead)
         {
             throw new InvalidCastException($"Type {duck.Name} does not have a {bindingFlags} get property {prop.Name}");
         }
         if (prop.CanWrite && !found.CanWrite)
         {
             throw new InvalidCastException($"Type {duck.Name} does not have a {bindingFlags} set property {prop.Name}");
         }
         return(found);
     }
     catch (AmbiguousMatchException)
     {
         throw new InvalidCastException($"Type {duck.Name} has an ambiguous match for property {prop.Name}"); //TODO: parameter list
     }
 }
Beispiel #11
0
 public static MethodInfo FindDuckMethod(this Type duck, MethodInfo method, BindingFlags bindingFlags, MissingMethods missingMethods)
 {
     try
     {
         var found = duck.GetMethod(method.Name, bindingFlags, null, method.ParameterTypes(), null);
         if (found == null && missingMethods == MissingMethods.NotImplemented)
         {
             return(null);
         }
         if (found == null)
         {
             throw new InvalidCastException($"Type {duck.Name} does not have a {bindingFlags} method {method.Name}");
         }
         return(found);
     }
     catch (AmbiguousMatchException)
     {
         throw new InvalidCastException($"Type {duck.Name} has an ambiguous match for {bindingFlags} method {method.Name}"); //TODO: parameter list
     }
 }
Beispiel #12
0
        internal static object Cast(object from, Type to, MissingMethods missingMethods)
        {
            var func = casts.GetOrAdd(new TypePair(from.GetType(), to, missingMethods), pair => CreateProxy(pair.From, pair.To, pair.MissingMethods));

            return(func(from));
        }