2012-07-15 51 views
2

我有一种情况,我需要知道如何以最好的方式处理它。C# - 加载DLL和创建实例

我有一个应用程序(MVC3),我有几个集成它。我有一个“IntegrationInterface”接口,每个集成都实现它。 我想加载集成的dll,创建它们的列表,并运行一个循环,为列表中的每个集成运行一个方法。

例如 - 假设我已经整合了facebook,myspace和twitter(用于我的应用程序),并且每当用户在我的应用程序中发布消息时,我都想在他的\ facebook上发布消息,myspace和twitter 。

我不希望这样的代码就知道我有积分,所以如果明天我将创建一个谷歌+一个新的集成,我只需要添加一个新的DLL而不改变我的应用程序的代码。

我该怎么做?

回答

5

首先,你必须找到所有相关的DLL和类:

​​

loadedIntegrationsList<Type>类型。然后,你可以分别给出集成和调用它的方法:

foreach(var integrationType in loadedIntegrations) 
{ 
    var ctor = integrationType.GetConstructor(new Type[] { }); 
    var integration = ctor.Invoke(new object[] { }) as IntegrationInterface; 
    //call methods on integration 
} 
+0

这里唯一的风险是如此有正确的下降有非托管的DLL的风险就会加载任何.dll文件? – 2012-07-15 11:53:20

+0

是的,这是正确的。我认为,他能够将错误处理纳入必要的程度。但这取决于确切的情况。 – 2012-07-15 11:57:34

0

我做类似于你在导入实用程序,写描述了一些东西。我的问题是我不想加载所有的程序集。我只想加载包含请求类型的程序集。

为了实现这一点,我使用了AppDomain.CurrentDomain.AssemblyResolve事件处理程序。

此事件处理程序恰好在AppDomain抛出异常通知未找到程序集之前引发。我执行与Nico在该处理程序中建议的类似的代码并返回所需的程序集。

注意:我有一个名为'任务'(想想导入任务)的子目录,我在那里存储我想在运行时加载的所有程序集。

下面是代码:

 var tasks = GetTasks(); 
     var basedir = AppDomain.CurrentDomain.BaseDirectory; // Get AppDomain Path 
     var tasksPath = Path.Combine(basedir, "Tasks"); // append 'Tasks' subdir 

     // NOTE: Cannot be factored, relies on 'tasksPath' variable (above). 
     AppDomain.CurrentDomain.AssemblyResolve += (s, e) => // defined 'AssemblyResolve' handler 
     { 
      var assemblyname = e.Name + ".dll"; // append DLL to assembly prefix 
      // *expected* assembly path 
      var assemblyPath = Path.Combine(tasksPath, assemblyname); // create full path to assembly 
      if (File.Exists(assemblyPath)) return Assembly.LoadFile(assemblyPath); // Load Assembly as file. 
      return null; // return Null if assembly was not found. (throws Exception) 
     }; 

     foreach (var task in tasks.OrderBy(q => q.ExecutionOrder)) // enumerate Tasks by ExecutionOrder 
     { 
      Type importTaskType = Type.GetType(task.TaskType); // load task Type (may cause AssemblyResolve event to fire) 
      if (importTaskType == null) 
      { 
       log.Warning("Task Assembly not found"); 
       continue; 
      } 
      ConstructorInfo ctorInfo = importTaskType.GetConstructor(Type.EmptyTypes); // get constructor info 
      IImportTask taskInstance = (IImportTask)ctorInfo.Invoke(new object[0]); // invoke constructor and cast as IImportTask 
      taskInstances.Add(taskInstance); 
     } 
     // rest of import logic omitted...