我已经根据常规做法创建了自己的插件架构,但我仍然坚持使用图标。
首先,我的插件定义了主机使用的客户端,每个客户端都定义了以下属性:
[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);
}
}
问题是在这个方法中我需要按原样发布图标文件,不能将它们添加到资源中。我很乐意听到一种方法,我仍然可以将图标嵌入资源中。
答案 0 :(得分:2)
您可以将它们添加到资源,然后从自定义属性访问资源。但是,您需要引用插件的程序集,因此您无法在构造函数中执行此操作。我会这样做:
[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
为空但_icon
不为时,_resourceName
属性getter可能会抛出异常,因为这意味着Resolve
未被调用,或者有一个问题。 (您仍应注意,即使Resolve
也可以抛出,因为GetManifestResourceStream
或Bitmap
构造函数可能会抛出。)
答案 1 :(得分:0)
无法将其添加到资源
为什么不呢?您可以将IconFile
定义为与插件在同一程序集中的资源名称。然后,给定包含插件的Assembly
,调用assembly.GetManifestResourceStream
并将该流传递给Bitmap
构造函数。
答案 2 :(得分:0)
感谢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);
}