C#解决方案系统的命令列表
我现在有一个运行了很长的步骤列表,例如C#程序:C#解决方案系统的命令列表
- 副本的文件从这里到那里 即: 的foreach(文件列表) File.Copy()
- 创建一批目录的 的foreach(目录列表) Directory.Create
- 循环进入目录的列表,并创建一个文件。 的foreach(在列表目录) File.Create()
- 取得文件的列表知道,更换内 的foreach(文件列表) 执行( “REPLACE.EXE”,文本1,文本2)
等
我所做的就是把所有这些步骤,并创建一批在C#是做那些步骤的方法。这样做的好处是,我可以检查每个运行的命令,记录任何问题等。它的缺点是,它是硬编码的。
我想(我需要)将这些步骤从代码中移出,如在配置文件或xml文件中,然后逐个读取命令并在c#中运行它们。通过这种方式,我仍然可以检查返回错误,创建日志等,但我没有实际的列表和命令硬编码。
我不想使用脚本(如Perl或批处理),因为我希望能够监视我所做的一些步骤。换句话说,我真的想在c#程序中保留实际的执行,但是程序由我提供给它的配置文件指导。
xml非常灵活,但我不确定我可以用它做所有事情。例如 我怎么变成XML是这样的:
list1 = {file1, file2};
list2 = {dir1,dir2,dir3};
foreach (file in list1)
File.Copy(file,dir2\\file);
File.Copy(file,dir3\\file);
什么我可以/应该使用来实现这一目标的任何想法?
感谢 托尼
这里是我的循环任务
[XmlAttribute]
public string DataTableName { get; set; }
public TaskListClass TaskList { get; set; }
public override void Execute(WorkContainer container)
{
int iteration = 0;
string originalTaskName=String.Empty;
// Log Start
base.Execute(container);
// Get the Data Table Based upon the ContainerKey
DataTable loopTable = container.GetKeyValue<DataTable>(DataTableName);
// If not found throw exception and exit
if (loopTable == null)
{
throw new ArgumentException(
"DataTable Not Found or Initialized For Loop Variable",
DataTableName);
}
// For each row returned run the task in order as a mini-process
foreach (DataRow row in loopTable.Rows)
{
iteration++;
foreach (TaskBase task in TaskList.Tasks)
{
// If it is the first iteration then create a new string with the iteration number
// else just replace the last iteration number with the current iteration number
if (iteration == 1)
{
task.Name = String.Format("Iteration {0} - {1}", iteration, task.Name);
}
else
{
task.Name = task.Name.Replace(String.Format("Iteration {0}",iteration-1),String.Format("Iteration {0}",iteration));
}
// Call the task Constructor to Initialize the object
task.GetType().GetConstructor(new Type[0]).Invoke(null);
foreach (DataColumn dc in loopTable.Columns)
{
// Store in Stack Variable
string propertyName = dc.ColumnName;
// If a field in the table matches a
// property Name set that property
PropertyInfo propInfo = task.GetType().GetProperty(propertyName);
if (propInfo != null)
{
propInfo.SetValue(task, row[dc], null);
}
else
{
// Else if the task has a Parameters collection add the
// name of the column and value to the Parameter Collection
propInfo = task.GetType().GetProperty("Parameters");
if (propInfo != null)
{
List<Parameter> parameters = propInfo.GetValue(task, null) as List<Parameter>;
// If the parameter Name already Exist then Override it
// This means that the values in the DataTable override the values in the XML
if (parameters.Contains(new Parameter { Name = propertyName }))
{
parameters.Remove(new Parameter { Name = propertyName });
}
parameters.Add(new Parameter { Name = propertyName, Value = row[dc].ToString(), Type="String" });
}
else
{
ParameterNotFoundException pExp = new ParameterNotFoundException(propertyName, task.GetType().ToString());
throw new TaskException("Unable to assign a Parameter", pExp.Message, pExp);
}
}
}
task.Execute(container);
}
}
base.Finish(container);
}
的XML看起来像这样
<LoopTask Name="Loop Report Creation" DataTableName="[? DistributionList ?]">
<TaskList>
<ReportBatchTask Name="Report In Loop">
<ConnectionName>xxx</ConnectionName>
<Parameters />
</ReportBatchTask>
</TaskList>
</LoopTask>
要做到你的要求,你就必须在代码中定义的每个可能的行动,因此,如果您创建一个新的动作,这将需要编辑的程序。尽管如此,配置现有操作不会有任何问题。
<TaskList>
<MyTask>
<Action type="CreateDirectory">
<target>dir1</target>
<target>dir2</target>
</Action>
</MyTask>
<MyTask>
<SourceFiles>
<file>mypath\file1.txt</file>
<file>mypath\file2.txt</file>
</SourceFile>
<Action type="Replace">
<originalText>Text to replace</originalText>
<replacementText>Some new text</replacementText>
</Action>
<Action type="Copy">
<target>dir1</target>
<target>dir2</target>
</Action>
</MyTask>
</TaskList>
如果你有一个单独的类为每一个可能Action
那么你将创建和使用你从XML在读什么执行适当Action
。
我真的很喜欢这个建议。我需要弄清楚循环,但大多数解决了我的问题。 感谢 托尼 – tony 2011-04-07 21:30:46
是的,我做了一个类似的项目:这里有一些想法,而不必键入整个事情。
我创建的任务,每个任务由Task类inherieted基本记录和
public virtual void Execute(WorkContainer container)
但每类做了这样的复制类将有一个来源,目的地和覆盖性能。
那我就创造出当时可能被序列化到XML任务列表的任务列表
看起来像
<TaskList>
<TransactionSqlTask Name="Get Interest Register Data">
<Parameters>
<Parameter>
<Type>String</Type>
<Value>M</Value>
<Name>PaymentInd</Name>
</Parameter>
</Parameters>
<DataTableName>
<string>InterestRegisterData</string>
</DataTableName>
<IgnoreOutputDataTable>false</IgnoreOutputDataTable>
<StoredProcName>proc_Report_NotesInterestRegister</StoredProcName>
<ConnectionName>xxx</ConnectionName>
</TransactionSqlTask>
...
XML可以是一个命令行参数将被读入,反序列化并返回到任务列表
然后,我只是循环访问List和Call。执行
现在还有一个工作容器将值从一个任务传递到另一个。看到这个帖子
Using Generics to return a literal string or from Dictionary<string, object>
后,我可以提供更多的细节,现在我没有这个项目盈我的,但希望这给了你一些想法。
这是一个很好的建议,它有一定的相似之处下一个建议。 感谢 托尼 – tony 2011-04-07 21:32:01
您是否考虑过将函数重写为MSBuild任务?
通过这种方式,您可以利用预先存在的msbuild任务,并将脚本编写为msbuild文件(它非常适合于任何构建过程)。 You can even debug MSBuild tasks
我还没有想过,但后来它可以追溯到我不必运行外部过程,就像是一个黑盒给我的最初的问题。 Perl脚本或批处理文件与使用msbuild相同。 Perl绝对是可调试的。我确实看到你在构建过程中很好地适应了msbuild。 感谢 托尼 – tony 2011-04-07 21:35:07
您不必调用外部程序..的MSBuild暴露了一个C#库,在这里看到:http://stackoverflow.com/questions/536539/how-to-call-msbuild-from-c – 2011-04-08 08:40:39
考虑使用PowerShell的呢? – 2011-04-06 16:49:00
我还没有想过,但这将是一个外部过程(我认为)。我老实说从来没有使用过PowerShell,所以我不知道这对我有什么帮助。 Tony – tony 2011-04-07 21:37:12
PowerShell可以作为外部进程启动,也可以从其他进程托管。例如,SQL Server Management Studio中允许在树视图中,您可以右键单击一个节点,并启动PowerShell的与该节点作为当前项目运行。 – 2011-04-07 21:46:49