Why doesn't XElement have a GetAttributeValue method? - c#

Sometimes I'd like to know the reasoning of certain API changes. Since Google hasn't helped me with this question, maybe StackOverflow can. Why did Microsoft choose to remove the GetAttribute helper method on XML elements? In the System.Xml world there was XmlElement.GetAttribute("x") like getAttribute in MSXML before it, both of which return either the attribute value or an empty string when missing. With XElement there's SetAttributeValue but GetAttributeValue wasn't implemented.
Certainly it's not too much work to modify logic to test and use the XElement.Attribute("x").Value property but it's not as convenient and providing the utility function one way (SetAttributeValue) but not the other seems weird. Does anyone out there know the reasons behind the decision so that I can rest easily and maybe learn something from it?

You are supposed to get attribute value like this:
var value = (TYPE) element.Attribute("x");
UPDATE:
Examples:
var value = (string) element.Attribute("x");
var value = (int) element.Attribute("x");
etc.
See this article: http://www.hanselman.com/blog/ImprovingLINQCodeSmellWithExplicitAndImplicitConversionOperators.aspx. Same thing works for attributes.

Not sure exactly the reason, but with C# extension methods, you can solve the problem yourself.
public static string GetAttributeValue(this XElement element, XName name)
{
var attribute = element.Attribute(name);
return attribute != null ? attribute.Value : null;
}
Allows:
element.GetAttributeValue("myAttributeName");

Related

Intercepting Property Assignment with Attributes

Is it possible to have an attribute placed on a property intercept an assignment call to that property?
An example of how I would use this is to make it so that a string property with this attribute on it would be set to string.Empty when the user assigns null.
I'm sure there are a lot of other possible uses for something like this, but at the moment this is what I'm looking for.
EDIT:
For example:
class A
{
[NotNullableString]
public string SomeString { get; set; }
}
And NotNullableStringAttribute would check the input value for the set and if it is null replace it with string.Empty instead.
If you want to do this using C# Attributes you will need to use IL weaving.
The most popular library is PostSharp : http://ayende.com/blog/3640/first-steps-with-post-sharp The express version is free : http://www.postsharp.net/aspects
If you insist that there be no post build step in your workflow AND you get to use attributes, then the answer is that it is currently not possible.

XmlSerializer and acceptable values

Hello I am working on an project in which I should serialize and deserialize my objects to Xml and back to objects. I use the XmlSerializer class in order to achieve this. So my problem is that I can't figure out how to prevent the serialization if the attribute value of an element is invalid. For example I have an element with name person which contain 1 attribute (name)
I would like to prevent the user to put other names than (Alex, Nick,..) in this attribute I need something like xsd restriction (pattern) in this case but for my model. How can I solve this problem?
If you just want conditional serialisation, you can do this with the ShouldSerialize* pattern. So if you have a property Name (for example), you can add:
public bool ShouldSerializeName() {
/* validate; return true to serialize, false to skip */
}
The method needs to be public for XmlSerializer, although the same pattern works in other places (System.ComponentModel, for example) even if no-public.
I'm not sure weather it is a good idea to ignore some data in certain circumstances, but if you really wanna do this, take a look at the IXmlSerializable Interface. I think implementing this interface manually will be the only way to fulfill your requirements.

Can XmlSerializer.Deserialize ever return null?

I ve been trying in a few different ways to get XmlSerializer.Deserialize to return null
however it doesnt seem possible
I tried with a class being null, malformated xml, well formatted xml .
I might be missing something obvious here, but is it possible ?
Just to clarify give a Class MyClass that is serializable I want a similar test to the following to pass
[Fact] //this is a the test attribute when using xUnit
public void When_xml_Something_Then_serialize_returns_null()
{
string serializedObject = "<?xml version=\"1.0\" encoding=\"utf-8\"?><MyClass xmlns:xsi=\"http://www.w3asdsadasdasd.org/2001/XMLSchema-instance\"></MyClass>";
using (var stringReader = new StringReader(serializedObject))
{
Assert.Null(new XmlSerializer(typeof(MyClass)).Deserialize(stringReader));
}
}
Tried different things in the serialized string, and i either get an exception or an empty instance of MyClass :(
Thanks
NOTE: there was a typo in this question, it is now corrected
NOTE 2: for a more detailed answer look at the comments.
Yes, Deserialize can return null when the input does not contain the XML that is expected. This is frequently seen when there is confusion of the XML namespaces. If the input contains a root element with the expected name, but in a different namespace, then null will be returned.
This is often seen when dealing with ASMX web services or with Web References, especially web references against RPC-style services, where the messages are described in terms of the XSD type of the message, and not in terms of the element.
Appearantly, you can view or download the code for the System.Xml part of the .NET framework. This lets you look in the source code to determine when it returns null.
For the future i answer this, Use IsNullable attribute for those property can be null
https://learn.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlelementattribute.isnullable

Create dynamic object with hierarchy from xml and c#

I want to create a dynamic object from a string of XML. Is there an easy way of doing this?
Example String.
<test><someElement><rep1>a</rep1><rep1>b</rep1></someElement></test>
I'm trying to create an mvc editor for passing data through nvelocity and would like people on the front end to input xml as there data for parsing.
Thanks in advance.
You need 2 things to achieve this :
1) Valid xml
2) C# class which has same data members as in your input xml.
You need to create one object of C# class then enumerate through all the elements of xml and when by using switch for each of the element name, you can take inner text property of that element and assign it to respective data member of object.
C# code might look like following (you need to fill in the gaps):
class test {
List<string> someElement;
}
class xmlEnum
{
static test createObject(string inputXml)
{
test t = new test();
// load input xml in XmlDocument class
// and start iterating thorugh all the elements
swithc(elementName)
{
case rep1:
t.someElement.add(element.innerText);
break;
// some more cases will go here
}
// finally return the object;
return t;
}
}
I hope this will help you.
I don't think there's a ready-made dynamic solution to this. If I understand your question correctly, you would like to do something like this.
SomeDynamicXmlObject test = new SomeDynamicXmlObject(yourteststring);
var rep1 = test.SomeElement.rep1;
The closest I can think of you could get to that, is to use XElement classes, something like this:
XElement test = XElement.Parse(yourteststring);
var rep1 = test.Element("SomeElement").Element("rep1");
If that's not good enough, I'm afraid you will have to write something yourself that will parse the xml and create the object on the fly. If you know in advance what the xml will look like, you could use shekhars code, but I guess from your comments that you don't.
If you have schema for xml available and if this is needed in dev/build environment then a round about way to do this will be
Use XSD tool to parse schema and generate code from it
Build the generated code using command line complier or compiler services to generate assmebly. Now you have a type available there that can be used.
Needless to say this will be a quite slow and out-of-proc tools will be used here.
Another (not an easy way but faster) way that would not have dev env dependencies would be to parse your xml and generate dynamic type using reflection. See this article to check how to use Reflection.Emit

Can attributes be added dynamically in C#?

Is it possible to add attributes at runtime or to change the value of an attribute at runtime?
This really depends on what exactly you're trying to accomplish.
The System.ComponentModel.TypeDescriptor stuff can be used to add attributes to types, properties and object instances, and it has the limitation that you have to use it to retrieve those properties as well. If you're writing the code that consumes those attributes, and you can live within those limitations, then I'd definitely suggest it.
As far as I know, the PropertyGrid control and the visual studio design surface are the only things in the BCL that consume the TypeDescriptor stuff. In fact, that's how they do about half the things they really need to do.
Attributes are static metadata. Assemblies, modules, types, members, parameters, and return values aren't first-class objects in C# (e.g., the System.Type class is merely a reflected representation of a type). You can get an instance of an attribute for a type and change the properties if they're writable but that won't affect the attribute as it is applied to the type.
You can't. One workaround might be to generate a derived class at runtime and adding the attribute, although this is probably bit of an overkill.
Well, just to be different, I found an article that references using Reflection.Emit to do so.
Here's the link: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , you will also want to look into some of the comments at the bottom of the article, because possible approaches are discussed.
No, it's not.
Attributes are meta-data and stored in binary-form in the compiled assembly (that's also why you can only use simple types in them).
I don't believe so. Even if I'm wrong, the best you can hope for is adding them to an entire Type, never an instance of a Type.
If you need something to be able to added dynamically, c# attributes aren't the way. Look into storing the data in xml. I recently did a project that i started w/ attributes, but eventually moved to serialization w/ xml.
Why do you need to? Attributes give extra information for reflection, but if you externally know which properties you want you don't need them.
You could store meta data externally relatively easily in a database or resource file.
Like mentionned in a comment below by Deczaloth, I think that metadata is fixed at compile time. I achieve it by creating a dynamic object where I override GetType() or use GetCustomType() and writing my own type. Using this then you could...
I tried very hard with System.ComponentModel.TypeDescriptor without success. That does not means it can't work but I would like to see code for that.
In counter part, I wanted to change some Attribute values.
I did 2 functions which work fine for that purpose.
// ************************************************************************
public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, description);
}
}
}
// ************************************************************************
public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, isReadOnly);
}
}
}
When faced with this situation, yet another solution might be questioning you code design and search for a more object-oriented way. For me, struggling with unpleasant reflection work arounds is the last resort. And my first reaction to this situation would be re-designing the code. Think of the following code, which tries to solve the problem that you have to add an attribute to a third-party class you are using.
class Employee {} // This one is third-party.
And you have code like
var specialEmployee = new Employee();
// Here you need an employee with a special behaviour and want to add an attribute to the employee but you cannot.
The solution might be extracting a class inheriting from the Employee class and decorating it with your attribute:
[SpecialAttribute]
class SpecialEmployee : Employee
{
}
When you create an instance of this new class
var specialEmployee = new SpecialEmployee();
you can distinguish this specialEmployee object from other employee objects. If appropriate, you may want to make this SpecialEmployee a private nested class.

Categories