Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Динамическая подгрузка необходимых длл


Автор: Exception 12.4.2005, 14:53
САБЖ.
Я где-то читал, что надо Assembly.LoadFrom, но как конкретно не знаю. Помогите pls.
ЗЫ Примеры желательно на VB .NET, но можете накалякать на C# или Delphi for .net smile

Автор: chipset 12.4.2005, 15:03
MSDN в данном случае рулит, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemreflectionassemblyclassloadfromtopic1.asp smile

Автор: mr.DUDA 12.4.2005, 15:32
P.S.
LoadFrom - только в случае, если надо загрузить длл из указанной директории. Есть ещё Assembly.Load, который позволяет грузить Assembly из (в порядке очерёдности) текущей директории, public-директории, из PrivateBinPath (указанных в .config-файле), из GAC, из массива байтов... Есть ещё LoadWithPartialName, который грузит сборку из GAC, по её частичному имени... Много чего есть smile
Добавлено @ 15:34
P.S. (2) а обычно используют не имя длл, а имя класса, который нужен. То есть, к примеру, plugin прописывается своим именем класса, а в программе, загружающей этот plugin, используется Type.GetType(name), и в итоге нужная длл-ка загружается автоматически, возвращается тип. (А потом уже можно юзать Activator.CreateInstance(type) или type.CreateInstance).

Автор: Exception 13.4.2005, 12:40
Вы уж меня извините за настойчивость, но проблема такова:
загружается класс с помощью LoadFrom и создается CreateInstance. Но в конструкторе есть такие параметры:
Код

Public Sub New(Gui as IGUI, Row As Short, Col As Short)

Почему-то, когда в массив я пихаю мои объекты, он все равно пишет MissingMethodException smile Но я еще попробую.

Автор: arilou 13.4.2005, 12:56
А ты не пробовал сделать так:
Код

    Assembly asm = Assebmly.LoadFrom("yourAssembly.dll");
    Type typ = asm.GetType("yourTime.Full.Name");
    ConstructorInfo ci = typ.GetConstructor(BindingFlags.ExactBinding, null, CallingConventions.Standard, 
            New System.Type[] {typeof(IGUI), typeof(short), typeof(short)}, null);
    
    object obj = ci.Invoke(new object[]{param1, param2, param3});


?

Автор: Exception 15.4.2005, 10:16
У меня лезет куча ошибок в твоем коде,
arilou.

А C# я плохо знаю, так что если уж на шарпе, то тогда без ошибок плз smile

Автор: arilou 15.4.2005, 11:58
Вот то же самое на VB:

Код

Imports System.Reflection

' ссылка на сборку
Dim asm As [Assembly] = [Assembly].LoadFrom("сюда пишешь путь к файлу сборки.dll")
' ссылка на экземпляр типа для класса, который тебе нужен
Dim typ As Type = asm.GetType("сюда пишешь полное имя типа, например MyNamespace1.MyNamespace2.MyType")
' ссылка на конструктор
Dim ci As ConstructorInfo = typ.GetConstructor(BindingFlags.ExactBinding, null, CallingConventions.Standard, _
  new Type() {GetType(Integer), GetType(String)}, Nothing)
' ^^^^^^^^^^^^^^^^^^^^^^^^^^^
' здесь ты передаешь массив типов, соответствующих параметрам того конструктора, который тебе нужен
' напимер, если у тебя есть Sub New(param1 as Integer, param2 as String), то надо передать
' new Type() {GetType(Integer), GetType(String)}. Надеюсь, идею ты понял.

' теперь вызываем найденный конструктор
Dim obj As Object = ci.Invoke(new Object(){12, "hello world!"})
'                                                ^^^^^^^^^^^^^^^^^^^^
' здесь передаешь параметры для конструктора. Типы должны соответствовать
' тем типам, которых он ожидает


Сорри за немного туманный первый пост, я думал, если ты заморачиваешься c Reflection, то, возможно, уже ориентируешься в вызовах.
Добавлено @ 11:59
в obj будет положен созданный экземпляр.

Автор: Exception 16.4.2005, 12:02
Возможно, я окончательно отупел smile , но у меня лезет, что ci = Nothing и естессно ci.InvokeMember не проходит.
Мой код:
Код

        Dim g As BaseClass.IGUI
        g = New GUIClass.Gui
        ' ссылка на сборку
        Dim asm As [Assembly] = [Assembly].LoadFrom("E:\dotNET\GameEngine\bin\Warriors\Test\test.dll")
        ' ссылка на экземпляр типа для класса, который тебе нужен
        Dim typ As Type = asm.GetType("Test.Test")
        ' ссылка на конструктор
        Dim ci As ConstructorInfo = typ.GetConstructor(BindingFlags.ExactBinding, Nothing, CallingConventions.Standard, _
          New Type() {GetType(BaseClass.IGUI), GetType(Byte), GetType(Byte)}, Nothing)
        ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^
        ' здесь ты передаешь массив типов, соответствующих параметрам того конструктора, который тебе нужен
        ' напимер, если у тебя есть Sub New(param1 as Integer, param2 as String), то надо передать
        ' new Type() {GetType(Integer), GetType(String)}. Надеюсь, идею ты понял.

        ' теперь вызываем найденный конструктор
        Dim obj As Object = ci.Invoke(New Object() {g, 5, 5})
        '                                                ^^^^^^^^^^^^^^^^^^^^
        ' здесь передаешь параметры для конструктора. Типы должны соответствовать
        ' тем типам, которых он ожидает

Конструктор Test.Test принимает IGUI,Byte и Byte.
Класс GUIClass.Gui реализует интерфейс BaseClass.IGUI. В референсах естессно есть BaseClass.dll и GuiClass.dll. ЧТО НЕ ТАК, НЕ ПОЙМУ!

Автор: mr.DUDA 16.4.2005, 15:45
Посмотри в отладке, что возвращает typ.GetConstructors( ), и есть ли среди полученных конструкторов тот, у которого аргументы совпадают с нужными тебе (с помощью ConstructorInfo.GetParameters( )).

Автор: Exception 17.4.2005, 12:13
По идее все должно работать: параметры - BaseClass.IGUI& , System.Byte и System.Byte.
Странно, может дело в BindingFlags? По крайней мере я решил проблему получением массива конструкторов и инвокированием первого из них.
Код

        Dim g As BaseClass.IGUI
        g = New GUIClass.Gui
        ' ссылка на сборку
        Dim asm As [Assembly] = [Assembly].LoadFrom("E:\dotNET\GameEngine\bin\Warriors\Test\test.dll")
        ' ссылка на экземпляр типа для класса, который тебе нужен
        Dim typ As Type = asm.GetType("Test.Test")
        ' ссылка на конструктор
        Dim ci As ConstructorInfo() = typ.GetConstructors()
        Dim obj As Object = ci(0).Invoke(New Object() {CType(g, BaseClass.IGUI), CByte(5), CByte(5)})

Всем спасибо,
mr.DUDA и arilou, вам плюсы в репу smile

Автор: arilou 18.4.2005, 11:08
Цитата(Run @ 17.4.2005, 12:13)
Странно, может дело в BindingFlags? По крайней мере я решил проблему получением массива конструкторов и инвокированием первого из них.

Согласен, задачу решает, но надо найти, в чем проблема. Я сегодня забодяжу тест, чтобы проверить.

Автор: arilou 18.4.2005, 13:09
Run-time error

Я сделал тест:

Код

' .......
    Dim ci As ConstructorInfo = typ.GetConstructor(BindingFlags.Default Or BindingFlags.Public Or _
BindingFlags.Instance, Nothing, CallingConventions.Standard,  _
New Type() {GetType(String), GetType(Byte)}, Nothing)
' .......


Подобрал комбинацию BindingFlags, которая нормально работает:
BindingFlags.Default Or BindingFlags.Public Or BindingFlags.Instance


Попробуй у себя.

Автор: Exception 19.4.2005, 11:59
Не-а. Не работает smile
Но это уже не важно smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)