Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically inherit from internal class via reflection [closed]

Is there a way to inherit from an internal abstract class in a dynamically generated runtime class (such as via reflection) using .NET Framework 4.0?

like image 632
EOG Avatar asked Dec 13 '11 22:12

EOG


3 Answers

Sure you can and you don't need reflection for that. The inherited class just needs to be in the same assembly :)

You can also setup friendship between assemblies: http://msdn.microsoft.com/en-us/library/0tke9fxk%28v=VS.100%29.aspx, which would allow access to internal classes of one assembly. This approach is sometimes useful in creating Unit-Test assemblies that need internal access to tested assemblies

like image 39
surfen Avatar answered Oct 07 '22 00:10

surfen


Out of a general sense of perversity in the face of things that shouldn't be possible, I gave it a go at seeing how far I would get at trying to create a class that inherited from System.CurrentSystemTimeZone (an internal class in mscorlib). It let's you get as far as creating a TypeBuilder but when you call CreateType it throws a TypeLoadException with the message "Access is denied: 'System.CurrentSystemTimeZone'."

A bit more fiddling as led me to conclude that you could create an assembly dynamically which had the strong name that identified it as a friend assembly of the assembly in which the internal type is defined. But then, in that case you could just code class Foo : CurrentSystemTimeZone anyway, with no trickery being left.

Anyway, the code as far as the line which throws is below, just in case anyone is in the mood for trying some even more perverse variant on the idea, and wants a starting point:

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

namespace ReflectPerversely
{
    class SuicidallyWrong
    {
        private static ModuleBuilder mb;
        public static Assembly ResolveEvent(Object sender, ResolveEventArgs args)
        {
            return mb.Assembly;
        }
        public static void Main(string[] args)
        {
            Assembly sys = Assembly.GetAssembly(typeof(string));
            Type ic = sys.GetType("System.CurrentSystemTimeZone",true);
            AssemblyName an = new AssemblyName();
            an.Name = "CheatingInternal";
            AssemblyBuilder ab = Thread.GetDomain().DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
            mb = ab.DefineDynamicModule("Mod", "CheatingInternal.dll");
            AppDomain currentDom = Thread.GetDomain();
            currentDom.TypeResolve += ResolveEvent;

            TypeBuilder tb = mb.DefineType("Cheat", TypeAttributes.NotPublic | TypeAttributes.Class, ic);

            Type cheatType = tb.CreateType();
        }
    }
}
like image 174
Jon Hanna Avatar answered Oct 06 '22 22:10

Jon Hanna


You can't. You can use types that aren't public using Assembly.GetType(), but you can't inherit from them. Jon Skeet explains in this article why it is generally a bad idea to access non-public members, and answers your question more in-depth than I could.

like image 22
aevitas Avatar answered Oct 06 '22 22:10

aevitas