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

发布于 2024-07-11 01:24:24 字数 437 浏览 7 评论 0原文

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

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

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

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

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

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

We're currently developing a new piece of hand-held software. I cant discuss the nature of the application, so I'll use an example instead.

We're designing hand-held software for managing a school. We want to modularise each aspect of the system so that different schools can use different features.

Our system will start with a main menu and a login screen. I'd like this to be the base of the system and be where the modules will be added to. I.e. I'll have a project called SchoolPda.

I then want to have different modules. I.e., I want a registration module that will handle student registrations. I want a classroom module for managing classroom cleanliness, etc.

The way I'd possibly see this working is including/not including different dlls and having the base system's main menu expose buttons to access those modules if the dlls exist. That's just the kind of thing we're after.

Does anyone have any experience doing something like this? What would be the best way of doing it? We don't need to worry about the database as the database will always be the full database, but aspects wont get populated if the associated modules do not exist.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

看透却不说透 2024-07-18 01:24:24

我参与过的项目采用了两种方式:

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

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

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

I have been in projects that have done it two ways:

  • In one project we did not deploy certain DLLs if the customers weren't licensed. That's what you are suggesting. It worked fine. Of course, there was no way to enable those modules without an additional install, but it made perfect sense for that app.

  • In another project we deployed everything and only exposed to the end-users the menus, buttons, etc. for which the customer was licensed. We did that because then the user could easily add-on an extra module by adding a license for it. When the license was added, the stuff magically showed up on next login.

So in my experience, I would say look at your licensing model as one big piece of your decision. Think about whether you would ever want to add those extra modules on the fly.

初见你 2024-07-18 01:24:24

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

I am currently also developing a application that runs on both Compact and Full framework and is built modular.

The way I implemented it is that it scans a location for dll's and enummerates over each type and looks if they have a "ScreenInfoAttribute" or "WidgetInfoAttribute" defined which contains usefull information about the class.

here's a snippet, it contains 3.5 code, but that's because we recently made the switch from 2.0, but the principle works in 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;
    }
欢烬 2024-07-18 01:24:24

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

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

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

I don't know if it'll work on the CLR but have a look at MEF, for creating a way to discover and load your dlls / modules. You could also have your modules have a GetMenuItem method (or something to such of the ilk) that gets the information required so your main menu can add a button.

Obviously, use a different design for your main menu if it makes sense, but you'll want it to truly be both modulized and extendible, so that you can write your core, and in the future continue to write new components, without having to change you core.

I'm sorry if this doesn't make the largest amount of sense. Just hoped to give you an idea in one direction.

一个人练习一个人 2024-07-18 01:24:24

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

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

Just let every Module implement a common interface. Add Methods like GetButtons() or GetActions().

You can then place infomation about the AssemblyName and the ClassName in a config - file.
Now its's easy to load the specified Assembly and create an instance of the class with Activator.CreateInstance, cast it to your interface and call the GetButtons(), etc. methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文