我有一种情况,我需要知道如何以最佳方式处理它。
我有一个应用程序(MVC3),我有几个集成。我有一个接口“IntegrationInterface”,每个集成都实现它。 我想加载集成的dll,创建它们的列表,并运行一个循环,为列表中的每个集成运行一个方法。
例如 - 假设我有facebook,myspace和twitter(我的应用程序)的集成,每次用户在我的应用程序中发布消息时,我想在他的\ facebook,myspace和twitter上发布消息。
我不希望代码知道我有哪些集成,所以如果明天我将为google +创建一个新的集成,我只需要添加一个新的DLL而不需要更改我的应用程序的代码。 / p>
我该怎么做?
答案 0 :(得分:5)
首先,您必须找到所有相关的dll和类:
loadedIntegrations.Clear();
if (!Directory.Exists(path))
return;
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] files = di.GetFiles("*.dll");
foreach (var file in files)
{
Assembly newAssembly = Assembly.LoadFile(file.FullName);
Type[] types = newAssembly.GetExportedTypes();
foreach (var type in types)
{
//If Type is a class and implements the IntegrationInterface interface
if (type.IsClass && (type.GetInterface(typeof(IntegrationInterface).FullName) != null))
loadedIntegrations.Add(type);
}
}
loadedIntegrations
的类型为List<Type>
。然后,您可以实例化每个集成并调用其方法:
foreach(var integrationType in loadedIntegrations)
{
var ctor = integrationType.GetConstructor(new Type[] { });
var integration = ctor.Invoke(new object[] { }) as IntegrationInterface;
//call methods on integration
}
答案 1 :(得分:0)
我正在做类似于您在编写的导入实用程序中描述的内容。我的问题是我不想加载所有程序集。我只想加载包含所请求类型的程序集。
为了实现这一点,我使用了AppDomain.CurrentDomain.AssemblyResolve事件处理程序。
在AppDomain抛出异常通知未找到程序集之前引发此事件处理程序。我执行类似于Nico在该处理程序中建议的代码并返回请求的程序集。
注意:我有一个名为“Tasks”的子目录(想想导入任务),我存储了我想在运行时加载的所有程序集。
以下是代码:
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...
答案 2 :(得分:-1)
如果您了解MEF(托管扩展性框架),这可能对您有所帮助,我个人使用它,但不得不说使用MEF和MVC并不简单,我想更多信息请访问