首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可配置/动态参数

可配置/动态参数
EN

Stack Overflow用户
提问于 2014-09-15 15:21:11
回答 1查看 347关注 0票数 0

我想要构建一个类似于管道的东西,在这里我可以放置命令(转换器、读者、作者.)在一起,就像一个线性工作流,并通过给定的命令参数将它们连接起来。一切都应该是可序列化的,一个干净的xml是必须的,因为在第一步中没有计划图形编辑器,所以对xml进行了编辑(在VS中支持生成的模式和intellisense,这并不痛苦)。

样本:

代码语言:javascript
复制
<DataCommand name="AboFileReader"> 
<connection>
  <parameter name="filename"  direction="in"  type="string">
  <parameter name="tabledata" direction="out" type="DataTable">
</connection>       
</DataCommand>
<DataCommand name="TrimConverter"> 
<connection>
  <param name="tabledata" direction="in"  type="DataTable" >
  <param name="tabledata" direction="out" type="DataTable" >
</connection> 
</DataCommand>     
<DataCommand name="AboDataConverter"> 
<connection>
  <param name="tabledata" direction="in"  type="DataTable"  >
  <param name="tabledata" direction="out"  type="DataTable" >
</connection> 
</DataCommand> 
<DataCommand name="AboSqlWriter"> 
<connection>
  <param name="tabledata"  direction="in"  type="DataTable" >
</connection> 
</DataCommand>

我想到了三种不同的方法,它们都有优点和缺点,我不知道该选择哪一种。

首先,我认为1是要走的路,但后来我想出了解决方案3。因为它提供了一个干净的xml,并且是本机可序列化的。对于下一步(编辑器),绑定到GUI应该很容易,并且属性网格进行反射并不是我的第一选择(反射总是丑陋的),拥有一组参数可以轻松地绑定到GUI。

也许1和3的组合是在启动时收集集合中所有参数的方法吗?

1.数据注释

代码语言:javascript
复制
[Parameter(Direction = "In", Description="...")]
public string FileName {get; set;}

[Parameter(Direction = "Out", Description="...")]
public DataTable Table {get; set;}

优点:+本机参数在编码时公开+智能感知

缺点:-原生序列化?-丑陋的xml?

2. Workflow样式

代码语言:javascript
复制
public InParameter<string> FileName {get; set;}

public OutParameter<DataTable> Table {get; set;}

优点:+编码+参数公开时的智能感知+序列化工作

缺点:-丑陋的xml?

3.填充构造函数的集合

代码语言:javascript
复制
ObservableCollection<Parameter> Parameters {get; set;}

public Init()
{
  Parameters.Add( new Parameter() { Name="FileName", Type = typeOf(string),    Direction="In",  Description="..." } );
  Parameters.Add( new Parameter() { Name="Table",    Type = typeOf(DataTable), Direction="Out", Description="..." } );
}

优点:+序列化作品+干净的xml

缺点:-在源代码中没有公开参数-编码时没有智能感知

你有什么经验和路要走?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-15 17:35:38

就我个人而言,我会选择一种不那么冗长的XML表示形式,比如:

代码语言:javascript
复制
<ReadFile filename="..." />
<Trim />
<Convert />
<WriteSQL />

我假设大多数操作都有特定的输入和输出类型,所以除非这应该是可配置的,否则没有必要详细说明。这消除了一堆属性,但不是全部,所以您的问题仍然存在。理想情况下,您需要的东西是:

  1. 在代码结构中是可见的--这用作文档,并让IDE帮助您。
  2. 易于序列化-没有重复的、容易出错的代码
  3. 它的序列化形式很容易阅读,所以您需要干净的XML。

您想要使用属性是因为1号,因为第二个属性,您需要自动确定哪些属性需要序列化--这就是反射出现的地方。因为第三个原因,您只想序列化那些可配置的字段,所以您需要一些东西来区分这些属性。

使用属性来指示要公开哪些属性是一个好主意,因为它清楚地传达了它们的意图。它还允许您忽略其他属性,这使序列化格式保持干净。您还可以选择只序列化公共属性,但属性提供了更大的灵活性。最坏的情况是,它们会使代码更加混乱。

下面是我设置基本知识的方法:

代码语言:javascript
复制
public interface IOperation
{
    Type InputType { get; }
    Type OutputType { get; }

    object GetOutput(object input);
}

每个操作都提供了自己的IOperation接口实现:

代码语言:javascript
复制
public class ReadFileOperation : IOperation
{
    [Parameter]
    public string Filename { get; set; }

    public Type InputType { get { return null; } } // No input
    public Type OutputType { get { return typeof(DataTable); } }

    public object GetOutput(object input)
    {
        // TODO: Read file into DataTable here!
    }
}

如果您确实有可以配置为使用不同输入或输出类型的操作,那么给InputTypeOutputType一个setter和一个[Parameter]属性应该可以很好地工作。

您可以编写一个函数,查找实现IOperation的所有类型,并为每个类型存储属性列表。然后,在解析或写入时,查找当前类型并使用其属性列表。这个函数只需要调用一次,如果性能确实有问题,您可以在应用程序启动时使用它的输出来生成解析/编写代码,但除非我真的必须这样做,否则我不会这样做。

代码语言:javascript
复制
public Dictionary<Type, List<PropertyInfo>> DetectParameterProperties()
{
    Dictionary<Type, List<PropertyInfo>> lookup = new Dictionary<Type, List<PropertyInfo>>();

    IEnumerable<Type> operations = Assembly
        .GetAssembly(typeof(IOperation))
        .GetTypes()
        .Where(t => t.IsClass && !t.IsAbstract && typeof(IOperation).IsAssignableFrom(t));

    foreach (Type operation in operations)
    {
        lookup[operation] = new List<PropertyInfo>();

        IEnumerable<PropertyInfo> parameters = operation.GetProperties().Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(ParameterAttribute)));
        foreach (PropertyInfo parameter in parameters)
            lookup[operation].Add(parameter);
    }

    return lookup;
}

请注意,随着您提供更多的配置选项,错误处理变得更加重要。一个简单的类型检查,以确保所有输入和输出类型匹配良好,但一些操作可能需要自己的检查,以确保它们不会以其他方式被错误配置。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25851481

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档