2017-09-07 3 views
0

J'ai ajouté la référence d'une DLL dans mon projet et j'ai réussi à accéder aux méthodes/classes de cette DLL.Réflexion: Initialiser l'objet Problème

code dans la DLL: (Je n'ai pas accès à modifier ce code)

//Dll: myDllName 
    Namespace myNamespace 
     Public Class MyClass 
       Private Sub New(ByVal parameter1 As Int64) 
        //Set some values 
       End Sub 

       Public Shared Function MyPublicFunction(ByVal Parameter1 As Int64,ByVal Parameter2 As INt64,ByVal Parameter2 As Int64) As MyClass 
       Dim retMyClass As New MyClass(Parameter1) 
       //Set Other Values 

       Return retMyClass 
      End Function 

      Public Function Post() As Boolean 
      //Do some operation 
      End Function 
     End Class 
    End Namespace 

Mon code où j'ai appelé ci-dessus DLL:

Dim myObj As myDllName.myNamespace.MyClass 
myObj = myDllName.myNamespace.MyClass.MyPublicFunction(Parameter1, Parameter2, Parameter3) 

myObj.Prop1 = MyVal1 
myObj.Prop2 = MyVal2 
myObj.Prop3 = MyVal1 
myObj.Post() 

Maintenant, ma condition est que je veux atteindre au-dessus de la tâche sans ajouter de référence de DLL au projet. J'ai donc essayé d'y parvenir avec réflexion.

Dim assembly As Reflection.Assembly = Reflection.Assembly.LoadFile("..\\myDllName.dll") 
Dim t As Type = assembly.GetType("myDllName.myNamespace.MyClass") 
Dim woFacadeinst As Object = Activator.CreateInstance(t) 

Mais lors de l'initialisation de l'objet, il me lance erreur Constructor sur le type

myDllName.myNamespace.MyClass

pas trouvé.

Je pense que c'est à cause de la méthode Private NEW dans ma classe de référence DLL. Quelqu'un peut-il aider avec ceci?

+0

Copie possible de [Comment vérifier si un type fournit un constructeur sans paramètre?] (Https://stackoverflow.com/questions/4681031/how-do-i-check-if-a-type-provides-a -parameterless-constructor) –

Répondre

1

Pour constructeur paramétrés utilisation GetConstructors() et Invoke() au lieu de Activator.CreateInstance() comme suit:

Dim constructor = t.GetConstructors(BindingFlags.NonPublic Or BindingFlags.Instance) 

Dim woFacadeinst As Object = constructor(0).Invoke(New Object() {5}) 

, car il faut plus de temps, vérifiez le graphique dans ce link et si la performance est vraiment important pour vous essayez de compiler les expressions lambda, c'est beaucoup plus rapide que les deux.

+0

Essayez cette réponse à la place –

+0

Pouvez-vous expliquer pourquoi il ne devrait pas utiliser le 'Activator.CreateInstance()' –

+0

Vérifiez ma réponse mise à jour :) –

0

Vous exécutez dans cette exception, car avec cette ligne

Dim woFacadeinst As Object = Activator.CreateInstance(t) 

vous essayez d'appeler un paramètre moins constructeur, qui n'existe pas.

Vous devez donc appeler Activator.CreateInstance() avec d'autres paramètres pour transmettre le paramètre requis au constructeur.

Private Sub New(ByVal parameter1 As Int64) 
    'Set some values 
End Sub 

Habituellement en C# I utilisé l'extrait suivant:

var woFacadeinst = Activator.CreateInstance(typeof(Class1), BindingFlags.NonPublic | BindingFlags.Instance, 
              null, new object[] { 5 }, null); 

et comme vb.Net:

Dim woFacadeinst As Object = Activator.CreateInstance(GetType(Class1), 
                 BindingFlags.NonPublic Or BindingFlags.Instance, 
                 Nothing, New Object(){ 5 }, Nothing) 

L'astuce pour obtenir le constructeur privé sont le droit Bindingflags et new object[]{ 5 } vous définissez le (s) paramètre (s) requis par le constructeur.


Conseil:Pour des raisons de performances un coup d'oeil à la Ali Ezzat Odeh' Answer.

Si vous souhaitez utiliser la méthode GetConstructor() vous pouvez le faire comme les # C suivants Snippet:

var test = typeof(Class1).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, 
              null, new Type[] { typeof(Int64) }, null) 
          ?.Invoke(new object[] { 64 }); 

Comme C# Exemple:

Classe:

public class Class1 
{ 
    private Class1(string myString) 
    { 
     MyIntProperty = 42; 
     MyStringProperty = myString; 
    } 

    private Class1(int myInt) 
    { 
     MyIntProperty = myInt; 
     MyStringProperty = "default"; 
    } 

    private Class1(Int64 myInt64) 
    { 
     MyInt64Property = myInt64; 
     MyStringProperty = "default"; 
    } 

    public string MyStringProperty { get; set; } 
    public int MyIntProperty { get; set; } 
    public Int64 MyInt64Property { get; set; } 
} 

et le extrait de test:

string testString = "Test"; 
int testInt = 123; 

var objArray = new object[1]; 

objArray[0] = testString; 
var testClass1 = Activator.CreateInstance(typeof(Class1), BindingFlags.NonPublic | BindingFlags.Instance, 
              null, objArray, null); 

objArray[0] = testInt; 
var testClass2 = Activator.CreateInstance(typeof(Class1), BindingFlags.NonPublic | BindingFlags.Instance, 
              null, objArray, null); 

var testCtorClass = typeof(Class1).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, 
                null, new Type[] { typeof(Int64) }, null) 
            ?.Invoke(new object[] { 64 }); 
0

vous pouvez essayer var myClass = FormatterServices.GetUninitializedObject(typeof(MyClass)); Ce api ne pas utiliser constructeur donc il n'a pas toutes les exigences du constructeur.