2016-11-22 5 views
2

В прошлом, я написал приложение, которое динамически загружает DLL и все его зависимости, основанные на значения в базе данных, как показано ниже (продезинфицировать некоторые параметры)Динамическая загрузка Ассамблеи

VB

Dim oType As System.Type 
Dim oAssembly As System.Reflection.Assembly 
Dim oObject As System.Object 
oAssembly = Assembly.LoadFrom(path) 
oType = oAssembly.GetType("LogicValidator") 
oObject = Activator.CreateInstance(oType) 

oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir) 
Console.WriteLine("Begin processing...") 
oObject.ProcessBatch(cm_uid) 

Теперь, когда я пишу что-то подобное в C#, ошибка присутствует перед созданием приложения, указав следующее:

C#

System.Type oType = default(System.Type); 
System.Reflection.Assembly oAssembly = default(System.Reflection.Assembly); 
System.Object oObject = null; 
oAssembly = Assembly.LoadFrom(path); 
oType = oAssembly.GetType("LogicValidator"); 
oObject = Activator.CreateInstance(oType); 
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir); 
Console.WriteLine("Begin processing..."); 
oObject.ProcessBatch(cm_uid); 

Ошибка

«объект» не содержит определение для «Инициализировать» и не метод расширения «инициализации» принимающий первый аргумент типа «объект» может быть найден (Вы не нашли используя директиву или ссылку на сборку?)

Как мое приложение C# идентифицирует, что метод не существует до компиляции, если он загружен во время выполнения?

Редактировать

Я вычеркнул ниже для целей, помогая другим, кто наткнуться на этот вопрос. Пока он указывает на ответ, другие ответили на него более красноречиво. :-)

Я хотел бы добавить, что нижеследующее работает, но только в том случае, если уже установлены загруженные сборки.

var DLL = Assembly.LoadFile(path); 
Type type = DLL.GetType("LogicValidator"); 
dynamic c = Activator.CreateInstance(type); 
c.Initialise("param1", "param2", "param3", audit, UserInfo, workingDir); 
Console.WriteLine("Begin processing..."); 
c.ProcessBatch(cm_uid); 

+1

Не используйте 'System.Object' для типа' oObject', используйте нужный тип (т. Е. 'LogicValidator'). В противном случае вам может понадобиться 'dynamic'. – DavidG

ответ

2

Если вы не знаете тип при компиляции вы можете использовать динамическое время выполнения, объявив тип dynamic:

var oAssembly = Assembly.LoadFrom(path); 
var oType = oAssembly.GetType("LogicValidator"); 
dynamic oObject = Activator.CreateInstance(oType); 
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir); 
Console.WriteLine("Begin processing..."); 
oObject.ProcessBatch(cm_uid); 

Однако, вы могли бы рассмотреть подход, при котором загруженный тип реализует известный интерфейс (который будет объявлен в сборке, на который ссылается как на надстройке и код):

public interface IProcessor 
{ 
    void Initialise(
     string param1, 
     string param2, 
     string param2, 
     AuditTail auditTrail, 
     UserInfo userInfo, 
     DirectoryInfo workingDir); 

    void ProcessBatch(int uid); 
} 

Вы можете создать экземпляр следующим образом и получить полную поддержку IntelliSense и тип проверки:

var oAssembly = Assembly.LoadFrom(path); 
var oType = oAssembly.GetType("LogicValidator"); 
IProcessor oObject = Activator.CreateInstance(oType); 
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir); 
Console.WriteLine("Begin processing..."); 
oObject.ProcessBatch(cm_uid); 
0

Вы должны изменить oObject тип данных dynamic следующим образом:

System.Type oType = default(System.Type); 
System.Reflection.Assembly oAssembly = default(System.Reflection.Assembly); 
dynamic oObject = null; 
oAssembly = Assembly.LoadFrom(path); 
oType = oAssembly.GetType("LogicValidator"); 
oObject = Activator.CreateInstance(oType); 
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir); 
Console.WriteLine("Begin processing..."); 
oObject.ProcessBatch(cm_uid); 

Подробнее о dynamic: dynamic (C# Reference)

+0

Спасибо за ответ, ты избил меня! Я обновил свой вопрос. –

0

Вам не нужно, чтобы бросить его в динамический, как говорят другие ответы, йо U также может продолжать использовать отражение, которое не будет ссылаться на DLR и должен быть быстрее, в этом случае, тем более, что вы уже загружаются необходимые отражения объектов:

var oAssembly = Assembly.LoadFrom(path); 
var oType = oAssembly.GetType("LogicValidator"); 
var oObject = Activator.CreateInstance(oType); 
var oInitialiseMethod = oType.GetMethod("Initialise"); //See note below the code. 
var oProcessBatchMethod = oType.GetMethod("ProcessBatch"); //See note below the code. 
oInitialiseMethod.Invoke(oObject, "param1", "param2", "param3", AuditTrail, UserInfo, workingDir); 
Console.WriteLine("Begin processing..."); 
oObject.ProcessBatch(cm_uid); 

Вы хотите использовать перегрузку Type.GetMethod, который принимает Type [] для параметров функции, чтобы сигнатуры совпадали. Я сделал это для вас, но я не знаю, какие именно из них.

См https://msdn.microsoft.com/en-us/library/system.type.getmethod(v=vs.110).aspx

Как сказал другой ответ, хотя, интерфейс является хорошим решением здесь - в зависимости от общей структуры приложения и, если это возможно, чтобы сделать для вашего сценария.