2

我有一种情况,我需要知道如何以最好的方式处理它。

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

例如 - 假设我集成了 facebook、myspace 和 twitter(用于我的应用程序),每次用户在我的应用程序中发布消息时,我都想在他的 facebook、myspace 和 twitter 上发布消息。

我不希望代码知道我有哪些集成,所以如果明天我要为 google+ 创建一个新的集成,我只需要添加一个新的 DLL 而不更改我的应用程序的代码。

我怎样才能做到这一点?

4

3 回答 3

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
}
于 2012-07-15T11:30:07.730 回答
0

我正在做类似于您在编写的导入实用程序中描述的事情。我的问题是我不想加载所有程序集。我只想加载包含所请求类型的程序集。

为此,我使用了AppDomain.CurrentDomain.AssemblyResolve事件处理程序。

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

注意:我有一个名为“Tasks”的子目录(想想 Import 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...
于 2012-07-15T11:50:04.327 回答
-1

如果您知道 MEF(托管可扩展性框架),这可能会对您有帮助

http://msdn.microsoft.com/en-us/library/dd460648.aspx

于 2012-07-15T12:01:39.180 回答