Instantiating an Internal class and casting it as

2019-05-20 19:17发布

问题:

Following up on InternalsVisibleTo. I have looked at c# Instantiating Internal class with private constructor, and this has helped but I'm trying to cast the returned object as the internal type and, honestly I'm not 100% that that is possible.

I'm trying the route of Reflection to fix this issue, but I'm having a tough time trying to figure out how to instantiate an internal type with private methods using reflection. I can go as far as pulling the type and getting the constructor and creating an object.

How would I preform the cast of the object if the type I wish to cast is an internal type.?

public object InitPrivateCoreObjects(string Type)
{
    Assembly Core = Assembly.Load("Stuff.Core, Version=0.3.3881.21340, Culture=neutral, PublicKeyToken=4fe470e63e2d354e");
    Type TypeToReflect = Core.GetType("Stuff.Core.AssemblyWithIdentifer");
    object o = Activator.CreateInstance(TypeToReflect);
    MethodInfo mi = TypeToReflect.GetMethod("AssemblyWithIdentifer");
    object newObject = mi.Invoke(o,null);
    //alternatively
    //ConstructorInfo ctor = TypeToReflect.GetConstructor(new Type[]{TypeToReflect.GetType()});
    //ctor.Invoke(newObject, null);

    return newObject;
}

I can get the type of the internal class,
I can call the constructor and instantiate an object of the type. However, since I don’t have any access to the internal type I can’t cast it and manipulate it from there.

I understand I can use Reflection.Emit to create a new class based on that type, but if I'm going that route then I might as well just copy the entire contents of the project I'm trying to access into my test project. This would be really wastefully and pointless and would require me to throw in stuff from other projects and creating a mess and it's absolutely not the route I want to go at this time.

I've seen examples accessing individual methods and properties but none that instantiate an entire class. I'm not 100% sure it's possible since in the order of operations reflection happens before access modifiers are looked at.

Can this be done, and if so, how?

For clairification sake I wanted to use the instantiated object for testing purposes and [Assembly:InternalsVisibleTo("")] wasn't working due to bug which I'm currently working around. See here for original question.

回答1:

Given that you only know the type at execution time, there's really no such concept as "returning the object as the internal type". Think about what you'd want the method signature to look like... there's no way you could express it.

If the calling code knows about it in a strongly typed way, you should make the code generic instead:

public T InitPrivateCoreObjects<T>()
{
    Type type = typeof(T);
    ...
    return (T) newObject;
}

... but if the calling code doesn't know about it, that's not helpful to it.

If you could explain more about why you think you want this ability, we could try to suggest alteratives.



回答2:

I can use Reflection.Emit to create a new class based on that type

Not really: code generated using Reflection.Emit follows the same rules as your own C#. You can't use it to bypass internal protection.

I've seen examples accessing individual methods and properties

That's what you'll need to do: use reflection to look up and invoke individual methods and properties.

A couple of alternatives:

  • Modify the internal class to implement some interface, and make that interface public. Call methods on the interface as normal.
  • Get [InternalsVisibleTo] working. This is the right way to go.


回答3:

This is not really a direct answer to your question, but you may find this useful:

ExposedObject

If you don't have access to the internal type, nor does that type implement any public interface that you consider sufficient to interact with it, but you know beforehand the names and signatures of members on that type, this is probably your best choice.