反思:初始化对象问题

时间:2017-09-07 08:25:11

标签: .net vb.net dll reflection

我在项目中添加了一个DLL的引用,并且成功地能够访问该DLL的方法/类。

DLL中的代码:(我无权修改此代码)

//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

我在上面调用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()

现在我的要求是我想在不向项目添加DLL引用的情况下实现上述任务。 所以我试图通过反思实现这一点。

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)

但是在对象初始化时,它会抛出类型为

的构造函数的错误
  

myDllName.myNamespace.MyClass

未找到。

我认为这是因为我的DLL引用类中的Private NEW方法。 有人可以帮忙吗?

3 个答案:

答案 0 :(得分:1)

对于参数化构造函数,请使用GetConstructors()Invoke()而不是Activator.CreateInstance(),如下所示:

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

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

因为需要更多时间,请查看此link中的图表,如果性能对您来说真的很重要,请尝试编译lambda表达式,它比两者都快。

答案 1 :(得分:0)

您遇到此异常,因为使用此行

Dim woFacadeinst As Object = Activator.CreateInstance(t)

你试图调用一个不存在的参数less constructor。

因此,您必须使用更多参数调用Activator.CreateInstance()以将所需参数传递给构造函数。

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

通常在C#中我使用了以下代码段:

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

和vb.Net:

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

获取私有构造函数的技巧是正确的Bindingflags 并使用new object[]{ 5 }设置构造函数所需的参数。

提示: 有关性能问题,请查看Ali Ezzat Odeh' Answer

如果您想使用GetConstructor()方法,可以执行以下C#代码段:

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

作为C#示例:

班级:

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; }
}

测试代码段

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 } );

答案 2 :(得分:0)

你可以尝试var myClass = FormatterServices.GetUninitializedObject(typeof(MyClass));这个api不使用任何构造函数,因此它没有任何构造函数要求。