Reputation: 31
I need to create a system which takes into account the current assembly and perform x action based on that (reflection).
The main idea is to assign attributes to methods, so it doesnt require lot of maintenance for the next years, but also new classes will be developed to similar situation with new attributes/methods.
The main problem is that I have different arguments for different classes (i'm inheriting from a abstract class)
Base class:
public abstract class HelpItem : INotifyPropertyChanged
{
public HelpItem()
{
}
string group;
SvgImage image;
string description;
string help;
string name;
public string Name
{
get { return name; }
set
{
name = value;
}
}
public string Help
{
get { return help; }
set
{
if (help == value)
return;
help = value;
OnPropertyChanged(this, new PropertyChangedEventArgs(nameof(Help)));
}
}
public string Group
{
get { return group; }
set
{
if (group == value)
return;
group = value;
OnPropertyChanged(this, new PropertyChangedEventArgs(nameof(Group)));
}
}
public string Description
{
get { return description; }
set
{
if (description == value)
return;
description = value;
OnPropertyChanged(this, new PropertyChangedEventArgs(nameof(Description)));
}
}
public SvgImage Image
{
get { return image; }
set
{
if (image == value)
return;
image = value;
OnPropertyChanged(this, new PropertyChangedEventArgs(nameof(Image)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(sender, e);
}
[Action("&Open")]
public abstract void Run();
public static IList<HelpAttribute> GetHelpItems()
{
return GetHelpItems<HelpItem>();
}
}
An use of this class will be:
public class PfdHelpItem : HelpItem
{
public PfdHelpItem(System.IO.MemoryStream stream, DevExpress.XtraBars.Docking2010.DocumentManager docManager)
{
DocManager = docManager;
Stream = stream;
}
public MemoryStream Stream { get; set; }
public DocumentManager DocManager { get; set; }
bool isExternal;
public bool IsExternal
{
get { return isExternal; }
set
{
if (isExternal == value)
return;
isExternal = value;
OnPropertyChanged(this, new PropertyChangedEventArgs(nameof(IsExternal)));
}
}
public override void Run()
{
...
}
[Action("Open &externally")]
public void RunExternal()
{
...
}
[Action("&Save as...")]
public void SaveAs()
{
...
}
}
Attribute class:
public abstract class HelpAttribute : Attribute
{
public HelpAttribute(string name, string title, string description)
{
Description = description;
Title = title;
Name = name;
}
public string Name { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
Then I have other child classes:
public class PdfHelpAttribute : HelpAttribute
{
public PdfHelpAttribute(string name, string title, string description)
: base(name, title, description)
{
}
}
Then the use of this attribute:
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
[Misc.Help.PdfHelp("MyFileName", "Title", "Desc")]
internal static byte[] MyPdfFile{
get {
object obj = ResourceManager.GetObject("MyPdfFile", resourceCulture);
return ((byte[])(obj));
}
}
So as the sample shows, in this case it will get PDF files from resource and deal with it, open, save, etc.
There's also OnlineHelp class, which is filled with url addresses and has other actions.
The Idea is to get all the HelpItems from reflection and show as needed.
Is there a known pattern to work with that situation?
Thanks in advance!
Upvotes: 0
Views: 503
Reputation: 188
One pattern that you can use is the following:
The reason for using interfaces as the common denominator, is that they are typically much fewer than all the types available, making the creation of the inventory quicker and consume less memory.
Example: Look at the Initialize
and GetTypesImplementingInterface
methods in the static Types
class of the Waher.Runtime.Inventory
nuget:
https://github.com/PeterWaher/IoTGateway/blob/master/Runtime/Waher.Runtime.Inventory/Types.cs
It can be combined with the TypesLoader
class to dynamically load all available assemblies during startup:
Upvotes: 1