假设我创建了一个带有属性的类:
public class User
{
private string _userID;
public string UserID
{
get { return _userID; }
set { _userID = value; }
}
}
我必须如何处理类和属性才能将方法附加到UserID属性,例如使用“dot”语法围绕用户ID生成Xml的方法:
User u = new User();
u.UserID = "Mike";
string xml = u.UserID.ToXml();
我可以弄清楚如何编写一个方法来将Xml标记放在UserID的值周围,但是我想要的方法是如何使用“dot”语法使该方法与属性一起使用。
所有这些答案都很有用,感谢大家的贡献。事实上,我标记为“被接受”的答案正是我所寻求的。我很欣赏扩展方法的注意事项(在此之前我从未听说过),当然在某些情况下将扩展方法应用于所有字符串可能会有问题,但在这种情况下我肯定想应用这个方法ToXml()到类中的所有字符串属性。正是医生所要求的。我对XmlSerialization非常熟悉,但在这种情况下需要避免它出于各种原因。
答案 0 :(得分:13)
有两种方法:
您正在操作的对象/值必须具有该方法(例如,当您控制对象定义时。)
public class UserIDObject
{
public string ToXML() {}
}
public class User
{
private UserIDObject _userID;
public UserIDObject UserID
{
get { return _userID; }
set { _userID = value; }
}
}
User u = new User();
u.UserID = = new UserIDObject("Mike");
string xml = u.UserID.ToXml();
或者您可以为对象实现Extension Method (MSDN)。 Geeks博客有一个很好的Extension Methods教程,如果你运行的是VS2008,它们可以应用于.NET 2.0。
public static class MyMethods
{
public static string ToXML(this string s) { }
}
由于扩展方法适用于该类类型的 ALL 对象,因此扩展方法是您要大量加权的方法。 (IE。我希望所有字符串能够调用.ToXML()吗?)
答案 1 :(得分:7)
你可以:
答案 2 :(得分:5)
您必须将该方法添加到属性的类型。在这种情况下,UserID是一个字符串,这意味着将其添加到字符串类型并使其可以从所有字符串访问。我不确定这是一个好主意,但如果你真的想要这样做:
public static class StringUtils
{
public string ToXmlElement(this string s, string elementName)
{
return string.Format("<{0}>{1}</{0}>", elementName, s);
}
}
这与你的函数签名并不完全匹配,但它更适合附加到更大的字符串类。唯一的另一种选择是使用不同的底层类型来保存您的UserID,也许是一个隐式转换为字符串的自定义类。
最后,如果您只是尝试以通用方式将用户类编写为Xml,请查看System.Xml.Serialization
命名空间。然后你可以像这样标记你的类,并使用XmlSerializer
实例来读或写类。
[Serializable]
public class User
{
private string _userID;
[XmlElement()]
public string UserID
{
get { return _userID; }
set { _userID = value; }
}
}
答案 3 :(得分:2)
嗯,简短的回答是,尽管可以通过扩展方法实现,但您不希望这样做。这是糟糕的形式,不一定是你想要的。
更好的技术将涉及利用.NET XML序列化并将其交给您的对象。它可以为你做XML魔术。
答案 4 :(得分:2)
你基本上有几种方法可以在C#3.0中完成这项任务,有些方法更直接,类似于你希望它如何工作,还有一些更少。首先,让我澄清为什么你可能不会立即明白如何完成这样的事情:
因为UserID
属性的类型为string
(如您所指定的),所以它的所有成员都被定义,因此仅限于String
的成员(至少在传统对象中) - 面向编程[OOP])。这包括当然的方法。您似乎想要添加ToXml
方法,如果没有访问属性类型(在这种情况下为System.String
),则无法进行此方法。
所以你的选择如下:
将属性的类型更改为自定义类(即UserIdentification
类),并将ToXml
方法添加到此类。在大多数情况下,说实话,这不是一个很好的解决方案,因为它增加了不必要的复仅在您需要添加与UserID
相关的多个方法/属性时才考虑它。
只需将ToXml
方法添加到您的User类(并将其称为GetIdXmlString
)。一个不错的解决方案,可能就是我在C#3.0之前选择的(可能还有,视具体情况而定)。
Extension methods。这是添加到最新版本的C#的一个很棒的功能,它允许您通过向特定语法定义的方法添加方法来“扩展”现有的类和接口。有关详细信息,请参阅链接的文章,但您的扩展方法基本上如下所示:
public static string ToXml(this string str)
{
// Code for function goes here.
}
然后,您可以简单地调用此方法,就好像它实际属于string
类一样。
但请注意,因为最后一种方法可能并不总是合适的(因为它可以应用于代码中所有类型字符串的对象)。如果你想编写一个通用的ToXml函数(带有重载?),它将各种对象转换成你自己的自定义XML格式,那么公平,否则你可能会更好地使用第二个建议。辅助类是另一种选择,虽然语法稍微不那么好,但它至少意味着ToXml方法不会出现在所有字符串中。
无论如何,希望这会有所帮助......
答案 5 :(得分:0)
好吧,你不会用 String 类型做到这一点。您将创建一个具有所有必需字符串处理方法的新类,但也实现了“ToXml()”方法。遗憾的是,您无法从字符串类本身派生,因此您必须实现包装器方法或其他一些提供您也想要的字符串处理功能的方法。
答案 6 :(得分:0)
而不是拥有一个字符串,你需要一个实际支持ToXml()
的类答案 7 :(得分:0)
我想你可能非常狡猾并通过AOP删除属性,用具有正确方法的代理类替换属性。但即使你这样做,你也可能不得不将你的新属性转换为某个界面 - 实际上是双重演员,即
IXmlable x = (IXmlable)(object)this.UserId;
x.ToXml();
这可能会破坏首先做到这一点。但是嘿 - 至少你会分开担忧,对吗?
说真的,我会选择上面提到的其他更简单的选择。除非你想成为AOP大师,否则就是这样。 :)
答案 8 :(得分:0)
您可以创建struct UserID
值类型,将方法添加到其中并在您的班级中使用它而不是string
。