Доработал решение с generic'ами. Проблемы :
-Вызывать через generic interface очень неудобно/невозможно.
-Нельзя получить список settings
-В каждой реализации IAction предполагается заново реализовывать свойства Name,Decription,TimeStart ...
В общем виде выглядит так :
public interface IAction // Этот интерфейс публикуется и используется Invoker'ом.
{
IActionResult Invoke(IContext context);
string Name { get;}
string Description { get;}
DateTime TimeStart { get;}
...
Dictionary<string, string> GetSettings();
}
internal abstract class BaseAction<TSetting> : IAction
where TSetting : BaseSettings
{
protected BaseAction(TSetting setting) // Добавить все required поля.
{
this.Setting = setting;
...
}
protected TSetting Setting {get; set;};
public abstract IActionResult Invoke(IContext context);
//......
//Реализация полей Name, Description , TimeStart ...
//......
Dictionary<string, string> IAction.GetSettings()
{
return this.Setting.GetSettings();
}
}
public abstract class BaseSettings
{
public Dictionary<string, string> GetSettings()
{
//Берём рефлекией все поля, маркнутые SettingsFieldAttribute и кладём в dictionary.
//SettingsFieldAttribute содержит User Friendly Name поля. Оно же ключ в dictionary.
}
}
public class ConcreateActionSettings : BaseSettings
{
[SettingsField("Settings name")]
public string Name {get; set;};
}
public class ConcreteAction : BaseAction<ConcreateActionSettings>
{
public ConcreteAction(ConcreateActionSettings settings) : base(settings)
{
}
public override IActionResult Invoke(IContext context)
{
Console.WriteLine(string.Format("Settings name is : {0}", Setting.Name)); // Можно работать с settings как с конкретным объектом.
return ActionResult.Success;
}
}