如何在 C# 中为插件创建 Icon 属性?

发布于 2024-09-15 09:19:11 字数 960 浏览 2 评论 0原文

我已经根据常见做法创建了自己的插件架构,但我仍坚持使用图标。

首先,我的插件定义了主机使用的客户端,每个客户端都定义了如下属性:

[Client("Heroes of Newerth", "Heroes of Newerth Chat Client", "hon_16.png")]

有了这个,我的主机应用程序可以读取插件/客户端的元信息,而无需实际创建它的实例,但我坚持使用图标部分。

如上面的示例所示,客户端可以传递位图文件名,在我的属性实现中,我可以这样处理它:

[AttributeUsage(AttributeTargets.Class)]
public class ClientAttribute : Attribute
{
    private string _name;
    private string _description;
    private Bitmap _icon;

    public string Name { get { return this._name; } }
    public string Description { get { return this._description; } }
    public Bitmap Icon { get { return this._icon; } }

    public ClientAttribute(string Name, string Description, string IconFile = null)
    {            
        this._name = Name;
        this._description = Description;
        this._icon = new Bitmap(IconFile);
    }
}

问题是,在这个方法中,我需要按原样发布我的版本的图标文件,并且无法添加它们到资源。我很高兴听到一种仍然可以将图标嵌入到资源中的方法。

I’ve created my own plugin architecture based on the common practices but I’m stuck with icons.

First of all my plugins define Clients to be used by the host and each Client is defined with attributes like:

[Client("Heroes of Newerth", "Heroes of Newerth Chat Client", "hon_16.png")]

With this my host application can read the plugin/client's metainfo without actually creating an instance of it but I’m stuck with the icon part.

As in the above example a client can pass a bitmap file name and in my attributes implementation I can handle it like this:

[AttributeUsage(AttributeTargets.Class)]
public class ClientAttribute : Attribute
{
    private string _name;
    private string _description;
    private Bitmap _icon;

    public string Name { get { return this._name; } }
    public string Description { get { return this._description; } }
    public Bitmap Icon { get { return this._icon; } }

    public ClientAttribute(string Name, string Description, string IconFile = null)
    {            
        this._name = Name;
        this._description = Description;
        this._icon = new Bitmap(IconFile);
    }
}

The problem is that within this method I need to publish the icon files with my release as is and can't add them to resources. I'll be happy to hear a method that I can still embed the icons in resources.

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

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

发布评论

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

评论(3

九命猫 2024-09-22 09:19:11

您可以将它们添加到资源中,然后从自定义属性访问资源。但是,您需要对插件程序集的引用,因此无法在构造函数中执行此操作。我会这样做:

[AttributeUsage(AttributeTargets.Class)]
public class ClientAttribute : Attribute
{
    private string _name;
    private string _description;
    private string _resourceName;
    private Bitmap _icon;

    public string Name { get { return this._name; } }
    public string Description { get { return this._description; } }
    public Bitmap Icon { get { return this._icon; } }

    public ClientAttribute(string name, string description, string resourceName = null)
    {
        _name = name;
        _description = description;
        _resourceName = resourceName;
    }

    public void ResolveResource(Assembly assembly)
    {
        if (assembly != null && _resourceName != null)
        {
            var stream = assembly.GetManifestResourceStream(_resourceName);
            if (stream != null)
                _icon = new Bitmap(stream);
        }
    }
}

当然,这意味着当您第一次检索自定义属性时,Icon 属性将返回 null,直到您使用正确的程序集调用 Resolve 为止。我已经编写了它,以便在出现问题时它保持为空;您需要决定是否要抛出异常。特别是,当 _icon 为 null 但 _resourceName 不是 null 时,Icon 属性 getter 可能应该抛出异常,因为这意味着 >Resolve 未调用,或者存在问题。 (您仍然应该注意,即使 Resolve 也可能会抛出异常,因为 GetManifestResourceStreamBitmap 构造函数可能会抛出异常。)

You can add them to the resources, and then access the resources from the custom attribute. However, you need a reference to the plugin’s assembly, so you can’t do it in the constructor. I would do it like this:

[AttributeUsage(AttributeTargets.Class)]
public class ClientAttribute : Attribute
{
    private string _name;
    private string _description;
    private string _resourceName;
    private Bitmap _icon;

    public string Name { get { return this._name; } }
    public string Description { get { return this._description; } }
    public Bitmap Icon { get { return this._icon; } }

    public ClientAttribute(string name, string description, string resourceName = null)
    {
        _name = name;
        _description = description;
        _resourceName = resourceName;
    }

    public void ResolveResource(Assembly assembly)
    {
        if (assembly != null && _resourceName != null)
        {
            var stream = assembly.GetManifestResourceStream(_resourceName);
            if (stream != null)
                _icon = new Bitmap(stream);
        }
    }
}

Of course, this means that when you first retrieve the custom attribute, the Icon property will return null until you call Resolve with the correct assembly. I’ve written it so that it stays null if there are problems; you need to decide whether you want to throw exceptions instead. In particular, maybe the Icon property getter should throw an exception when _icon is null but _resourceName isn’t, because then it means that Resolve wasn’t called, or there was a problem. (You should still be aware that even Resolve can throw because GetManifestResourceStream or the Bitmap constructor might throw.)

一刻暧昧 2024-09-22 09:19:11

无法将它们添加到资源

为什么不呢?您可以将 IconFile 定义为与插件位于同一程序集中的资源名称。然后,给定包含插件的 Assembly,调用 assembly.GetManifestResourceStream 并将该流传递给 Bitmap 构造函数。

can't add them to resources

Why not? You could define IconFile as the name of a resource within the same assembly as the plugin. Then, given an Assembly that contains the plugin, call assembly.GetManifestResourceStream and pass that stream to the Bitmap constructor.

另类 2024-09-22 09:19:11

感谢 timwi 这是我的最终实现;

    internal void ResolveResources(Assembly _assembly)
    {
        if (_assembly != null && this._icon_name != null)
        {                   
            var stream = _assembly.GetManifestResourceStream(string.Format("{0}.Resources.{1}",_assembly.GetName().Name,this._icon_name));
            if (stream != null) this._icon = new Bitmap(stream);
        }
    }

在我的 PluginInfo 类中,我调用解析器;

            else if(t.IsSubclassOf(typeof(Client)))
            {
                object[] _attr = t.GetCustomAttributes(typeof(ClientAttribute), true);
                (_attr[0] as ClientAttribute).ResolveResources(this._assembly);
            }

Thanks to timwi here's my final implementation;

    internal void ResolveResources(Assembly _assembly)
    {
        if (_assembly != null && this._icon_name != null)
        {                   
            var stream = _assembly.GetManifestResourceStream(string.Format("{0}.Resources.{1}",_assembly.GetName().Name,this._icon_name));
            if (stream != null) this._icon = new Bitmap(stream);
        }
    }

And in my PluginInfo class i call the resolver;

            else if(t.IsSubclassOf(typeof(Client)))
            {
                object[] _attr = t.GetCustomAttributes(typeof(ClientAttribute), true);
                (_attr[0] as ClientAttribute).ResolveResources(this._assembly);
            }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文