我们目前正在开发一款新的手持式软件。我无法讨论应用程序的性质,因此我将使用一个示例来代替。

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

我们的系统将以主菜单和登录屏幕启动。我希望这是系统的基础,也是添加模块的地方。IE。我将有一个名为 SchoolPda 的项目。

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

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

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

有帮助吗?

解决方案

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

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

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

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

其他提示

我目前还在开发一个在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;
    }

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

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

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

让每个模块实现一个通用接口。添加GetButtons()或GetActions()等方法。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top