我知道我可以使用简单的Console.WriteLine和Console.ReadLine方法进行输出/输入,但是那样的话,我在进程之间传递了一个字符串(必须对其进行解析才能重新创建对象)。
我想知道的是,是否可以通过管道传递自己的类型,以便在命运过程中轻松检索它们。我期望做的是:
myProgram | get-member
输出将类似于MyNameSpace.MyType及其成员列表(当前显示typeName System.String)。
是否可以在控制台应用程序中做到这一点,还是只能使用cmdlet做到这一点?
最佳答案
最简单的方法是使用序列化将希望从一个对象发送到另一个对象的对象转换为可管道传输的格式,以将它们从一个对象发送到另一个对象。但是,这样做有很多限制:
首先,您要来回传递的类型的实现必须对可能处理它们的所有应用程序可用。 (对于PowerShell,这不是问题,因为所有cmdlet都在同一进程中运行。)因此,最简单的方法是在所有控制台应用程序引用的类库中创建要传递的类型。举例来说,我在此类中加入了示例共享库:
[Serializable]
public class TestClass
{
public string Test { get; set; }
public string TestAgain { get; set; }
public string Cheese { get; set; }
}
[Serializable]属性将其标记为可序列化的,对于简单的类而言已足够。对于更复杂的类,可能需要更多类-请参见MSDN,从此处开始:http://msdn.microsoft.com/en-us/library/4abbf6k0(v=VS.71).aspx
然后,在您要传递的程序中,将其序列化为XML并将其写到控制台,如下所示:
using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using Shared;
namespace Out
{
class Program
{
static void Main(string[] args)
{
// Create the object.
TestClass test = new TestClass();
test.Test = "Monkey";
test.TestAgain = "Hat";
test.Cheese = "Fish";
// Serialize it.
XmlSerializer serializer = new XmlSerializer(typeof (TestClass));
StringBuilder sb = new StringBuilder();
using (var writer = new StringWriter(sb))
serializer.Serialize(writer, test);
// And write it to console.
Console.WriteLine(sb.ToString());
}
}
}
运行时,这将输出以XML编码的实例属性,因此:
<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http
://www.w3.org/2001/XMLSchema">
<Test>Monkey</Test>
<TestAgain>Hat</TestAgain>
<Cheese>Fish</Cheese>
</TestClass>
然后,在接收应用程序中,从控制台读取结果,以逆转该过程,从而:
using System;
using System.IO;
using System.Xml.Serialization;
using Shared;
namespace In
{
class Program
{
static void Main(string[] args)
{
// Read the input XML; until complete.
string input = Console.In.ReadToEnd();
TestClass passedIn;
// Deserialize it.
var serializer = new XmlSerializer(typeof (TestClass));
using (var reader = new StringReader(input))
passedIn = (TestClass) serializer.Deserialize(reader);
// Do something with the object.
Console.WriteLine("Test: {0}", passedIn.Test);
Console.WriteLine("TestAgain: {0}", passedIn.TestAgain);
Console.WriteLine("Cheese: {0}", passedIn.Cheese);
}
}
}
瞧!
C:\Working\PipeExample\In\bin\Debug>..\..\..\Out\bin\Debug\Out.exe | in
Test: Monkey
TestAgain: Hat
Cheese: Fish
当然,您将需要一些其他代码,以确保接收应用程序知道期望的类型-或可以处理它得到的任何内容-并且由于中间XML不是很容易解析的,因此您需要一种确保发送应用程序知道何时与管道交谈以及何时与人类交谈的方法。在.NET 4.5中,Console.IsOutputRedirected()方法将为您做到这一点(http://msdn.microsoft.com/en-us/library/system.console.isoutputredirected%28v=VS.110%29.aspx),但是在早期版本中,没有简单的方法可以通过编程方式获取此信息。
但这是事情的核心,查看XmlSerializer及其周围的文档将为您提供其余的知识。
关于c# - 如何在C#控制台应用程序(如Powershell)中传递自定义类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14515089/