模块化C#Compact Framework 2.0应用程序

时间:2009-01-06 09:59:59

标签: c# .net module compact-framework modularization

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

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

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

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

我可能看到这种工作方式包括/不包括不同的dll,如果dll存在,基本系统的主菜单会显示按钮来访问这些模块。这就是我们追求的那种东西。

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

4 个答案:

答案 0 :(得分:3)

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

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

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

根据我的经验,我会说你的许可模式是你决定的一个重要部分。想想你是否想要动态添加这些额外的模块。

答案 1 :(得分: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;
    }

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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

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