基于 class 方法的 C# 构造函数模式
C# Constructor Pattern based on class methods
我需要创建一个考虑当前程序集的系统并基于该程序集执行 x 操作(反射)。
主要思想是将属性分配给方法,因此在未来几年不需要大量维护,而且新的classes 将开发到与新的attributes/methods 类似的情况。
主要问题是我对不同的 class 有不同的论点(我继承自抽象 class)
基础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>();
}
}
这个 class 的用途是:
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()
{
...
}
}
属性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; }
}
那我还有其他的childclasses:
public class PdfHelpAttribute : HelpAttribute
{
public PdfHelpAttribute(string name, string title, string description)
: base(name, title, description)
{
}
}
那么这个属性的使用:
/// <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));
}
}
因此如示例所示,在这种情况下,它将从资源中获取 PDF 文件并对其进行处理、打开、保存等。
还有在线帮助 class,其中包含 url 个地址并具有其他操作。
想法是从反射中获取所有帮助项并根据需要显示。
是否有已知的模式可以处理这种情况?
提前致谢!
您可以使用的一种模式如下:
- 为您要查找的所需功能定义一个接口。
- 实现抽象基中的接口class。
- 创建清单class。
- 用一组程序集初始化库存class。该集合可以静态定义,也可以通过循环遍历应用程序域中的可用程序集来动态定义。
- 遍历程序集中的所有类型。
- 遍历这些类型(和基本类型)中的所有接口
- 使用适当的结构构建可用于实现不同接口的类型的清单。
- 添加一个方法以在需要时在运行时获取可用类型。
使用接口作为共同点的原因是,它们通常比所有可用类型少得多,从而可以更快地创建清单并消耗更少的内存。
示例:查看 Waher.Runtime.Inventory
nuget 的静态 Types
class 中的 Initialize
和 GetTypesImplementingInterface
方法:
https://github.com/PeterWaher/IoTGateway/blob/master/Runtime/Waher.Runtime.Inventory/Types.cs
它可以与 TypesLoader
class 结合使用以在启动期间动态加载所有可用程序集:
我需要创建一个考虑当前程序集的系统并基于该程序集执行 x 操作(反射)。
主要思想是将属性分配给方法,因此在未来几年不需要大量维护,而且新的classes 将开发到与新的attributes/methods 类似的情况。
主要问题是我对不同的 class 有不同的论点(我继承自抽象 class)
基础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>();
}
}
这个 class 的用途是:
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()
{
...
}
}
属性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; }
}
那我还有其他的childclasses:
public class PdfHelpAttribute : HelpAttribute
{
public PdfHelpAttribute(string name, string title, string description)
: base(name, title, description)
{
}
}
那么这个属性的使用:
/// <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));
}
}
因此如示例所示,在这种情况下,它将从资源中获取 PDF 文件并对其进行处理、打开、保存等。
还有在线帮助 class,其中包含 url 个地址并具有其他操作。
想法是从反射中获取所有帮助项并根据需要显示。
是否有已知的模式可以处理这种情况?
提前致谢!
您可以使用的一种模式如下:
- 为您要查找的所需功能定义一个接口。
- 实现抽象基中的接口class。
- 创建清单class。
- 用一组程序集初始化库存class。该集合可以静态定义,也可以通过循环遍历应用程序域中的可用程序集来动态定义。
- 遍历程序集中的所有类型。
- 遍历这些类型(和基本类型)中的所有接口
- 使用适当的结构构建可用于实现不同接口的类型的清单。
- 添加一个方法以在需要时在运行时获取可用类型。
使用接口作为共同点的原因是,它们通常比所有可用类型少得多,从而可以更快地创建清单并消耗更少的内存。
示例:查看 Waher.Runtime.Inventory
nuget 的静态 Types
class 中的 Initialize
和 GetTypesImplementingInterface
方法:
https://github.com/PeterWaher/IoTGateway/blob/master/Runtime/Waher.Runtime.Inventory/Types.cs
它可以与 TypesLoader
class 结合使用以在启动期间动态加载所有可用程序集: