c #, interne et réflexion
-
03-07-2019 - |
Question
Existe-t-il un moyen d'exécuter " internal " code par réflexion?
Voici un exemple de programme:
using System;
using System.Reflection;
namespace ReflectionInternalTest
{
class Program
{
static void Main(string[] args)
{
Assembly asm = Assembly.GetExecutingAssembly();
// Call normally
new TestClass();
// Call with Reflection
asm.CreateInstance("ReflectionInternalTest.TestClass",
false,
BindingFlags.Default | BindingFlags.CreateInstance,
null,
null,
null,
null);
// Pause
Console.ReadLine();
}
}
class TestClass
{
internal TestClass()
{
Console.WriteLine("Test class instantiated");
}
}
}
La création d'une classe de test fonctionne normalement parfaitement. Cependant, lorsque j'essaie de créer une instance par réflexion, une erreur missingMethodException m'indique qu'elle ne peut pas trouver le constructeur (ce qui arriverait si vous essayiez de l'appeler de l'extérieur de l'assembly). .
Est-ce impossible ou existe-t-il une solution de contournement que je peux faire?
La solution 2
Basé sur l'orientation de Preets vers un autre poste:
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace ReflectionInternalTest
{
class Program
{
static void Main(string[] args)
{
Assembly asm = Assembly.GetExecutingAssembly();
// Call normally
new TestClass(1234);
// Call with Reflection
asm.CreateInstance("ReflectionInternalTest.TestClass",
false,
BindingFlags.Default | BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic,
null,
new Object[] {9876},
null,
null);
// Pause
Console.ReadLine();
}
}
class TestClass
{
internal TestClass(Int32 id)
{
Console.WriteLine("Test class instantiated with id: " + id);
}
}
}
Cela fonctionne. (Ajout d'un argument pour prouver que c'était une nouvelle instance).
s’avère que j’ai juste besoin de l’instance et des BindingFlags non publics.
Autres conseils
Voici un exemple ...
class Program
{
static void Main(string[] args)
{
var tr = typeof(TestReflection);
var ctr = tr.GetConstructor(
BindingFlags.NonPublic |
BindingFlags.Instance,
null, new Type[0], null);
var obj = ctr.Invoke(null);
((TestReflection)obj).DoThatThang();
Console.ReadLine();
}
}
class TestReflection
{
internal TestReflection( )
{
}
public void DoThatThang()
{
Console.WriteLine("Done!") ;
}
}
Utilisez l'encapsuleur dynamique AccessPrivateWrapper si vous êtes en C # 4.0 http://amazedsaint.blogspot.com/2010/05/accessprivatewrapper-c-40-dynamic.html