2

我们目前正在开发一种新的手持软件。我无法讨论应用程序的性质,所以我将使用一个示例。

我们正在设计用于管理学校的手持软件。我们希望将系统的各个方面模块化,以便不同的学校可以使用不同的功能。

我们的系统将从主菜单和登录屏幕开始。我希望这是系统的基础,并且是添加模块的地方。即,我将有一个名为 SchoolPda 的项目。

然后我想要不同的模块。即,我想要一个可以处理学生注册的注册模块。我想要一个用于管理教室清洁等的教室模块。

我可能看到这种工作的方式是包括/不包括不同的 dll,并且如果存在 dll,则让基本系统的主菜单公开按钮以访问这些模块。这正是我们所追求的。

有没有人有做这样的事情的经验?最好的方法是什么?我们不需要担心数据库,因为数据库将始终是完整的数据库,但如果相关模块不存在,则不会填充方面。

4

4 回答 4

3

我参与的项目有两种方式:

  • 在一个项目中,如果客户没有获得许可,我们不会部署某些 DLL。这就是你的建议。它工作得很好。当然,如果不进行额外安装,就无法启用这些模块,但它对那个应用程序来说非常有意义。

  • 在另一个项目中,我们部署了所有内容,只向最终用户公开了客户获得许可的菜单、按钮等。我们这样做是因为用户可以通过为其添加许可证来轻松添加额外的模块。添加许可证后,这些东西神奇地出现在下次登录时。

因此,根据我的经验,我会说将您的许可模式视为您决策的一个重要部分。考虑一下您是否想要即时添加这些额外的模块。

于 2009-01-06T10:09:09.930 回答
3

我目前还在开发一个在 Compact 和 Full 框架上运行并且是模块化构建的应用程序。

我实现它的方式是它扫描 dll 的位置并枚举每种类型,并查看它们是否定义了“ScreenInfoAttribute”或“WidgetInfoAttribute”,其中包含有关该类的有用信息。

这是一个片段,它包含 3.5 的代码,但那是因为我们最近从 2.0 进行了切换,但原理在 2.0 中有效

public void Analyze(FileInfo file) {
        Assembly asm = Assembly.LoadFrom(file.FullName);
        List<Data.AnyPlugin> types = GetPluginTypes(asm.GetTypes());

        if (types.Count > 0) {
            types.ForEach(x => x.AssemblyPath = file.FullName);
            if (_plugins.ContainsKey(file.FullName)) {
                _plugins[file.FullName].Plugins.AddRange(types);
            } else {
                AssemblyPlugin asp = new AssemblyPlugin();
                asp.Ass = asm;
                asp.Plugins = types;
                _plugins.Add(file.FullName, asp);
            }
        }
    }

    private List<Data.AnyPlugin> GetPluginTypes(Type[] types) {
        List<Data.AnyPlugin> returnTypes = new List<AnyPlugin>();
        foreach (Type t in types) {
            Data.AnyPlugin st = GetPluginType(t);
            if (st != null) returnTypes.Add(st);
        }
        return returnTypes;
    }

    private Data.AnyPlugin GetPluginType(Type type) {
        if (type.IsSubclassOf(typeof(Screens.bScreen<T>))) {
            Screens.ScreenInfoAttribute s = GetScreenAttrib(type);
            if (s != null) {
                return new Data.ScreenPlugin("", type, s);
            }
        } else if (type.IsSubclassOf(typeof(Widgets.bWidget<T>))) {
            Widgets.WidgetInfoAttribute w = GetWidgetAttrib(type);
            if (w != null) return new Data.WidgetPlugin("", type, w);
        }
        return null;
    }

    private Screens.ScreenInfoAttribute GetScreenAttrib(Type t) {
        Attribute a = Attribute.GetCustomAttribute(t, typeof(Screens.ScreenInfoAttribute));
        return (Screens.ScreenInfoAttribute)a;
    }
于 2009-01-06T10:16:14.423 回答
0

我不知道它是否适用于 CLR,但请查看MEF,以创建一种发现和加载 dll / 模块的方法。你也可以让你的模块有一个 GetMenuItem 方法(或类似的东西)来获取所需的信息,这样你的主菜单就可以添加一个按钮。

显然,如果有意义的话,为你的主菜单使用不同的设计,但你会希望它真正模块化和可扩展,这样你就可以编写你的核心,并且在未来继续编写新的组件,而不必改变你的核心。

如果这没有最大的意义,我很抱歉。只是希望给你一个方向的想法。

于 2009-01-06T10:10:08.617 回答
0

只需让每个 Module 实现一个通用接口即可。添加 GetButtons() 或 GetActions() 等方法。

然后,您可以将有关 AssemblyName 和 ClassName 的信息放在配置文件中。现在很容易加载指定的程序集并使用 Activator.CreateInstance 创建类的实例,将其转换为您的接口并调用 GetButtons() 等方法。

于 2009-01-06T12:22:10.443 回答