The code looks like this:
StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (XmlWriter xmlWriter = XmlWriter.Create(builder, settings))
{
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
s.Serialize(xmlWriter, objectToSerialize);
}
The resulting serialized document includes namespaces, like so:
<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns="urn:something">
...
</message>
To remove the xsi and xsd namespaces, I can follow the answer from How to serialize an object to XML without getting xmlns=”…”?.
I want my message tag as <message> (without any namespace attributes). How can I do this?
...
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
s.Serialize(xmlWriter, objectToSerialize, ns);
This is the 2nd of two answers.
If you want to just strip all namespaces arbitrarily from a document during serialization, you can do this by implementing your own XmlWriter.
The easiest way is to derive from XmlTextWriter and override the StartElement method that emits namespaces. The StartElement method is invoked by the XmlSerializer when emitting any elements, including the root. By overriding the namespace for each element, and replacing it with the empty string, you've stripped the namespaces from the output.
public class NoNamespaceXmlWriter : XmlTextWriter
{
//Provide as many contructors as you need
public NoNamespaceXmlWriter(System.IO.TextWriter output)
: base(output) { Formatting= System.Xml.Formatting.Indented;}
public override void WriteStartDocument () { }
public override void WriteStartElement(string prefix, string localName, string ns)
{
base.WriteStartElement("", localName, "");
}
}
Suppose this is the type:
// explicitly specify a namespace for this type,
// to be used during XML serialization.
[XmlRoot(Namespace="urn:Abracadabra")]
public class MyTypeWithNamespaces
{
// private fields backing the properties
private int _Epoch;
private string _Label;
// explicitly define a distinct namespace for this element
[XmlElement(Namespace="urn:Whoohoo")]
public string Label
{
set { _Label= value; }
get { return _Label; }
}
// this property will be implicitly serialized to XML using the
// member name for the element name, and inheriting the namespace from
// the type.
public int Epoch
{
set { _Epoch= value; }
get { return _Epoch; }
}
}
Here's how you would use such a thing during serialization:
var o2= new MyTypeWithNamespaces { ..intializers.. };
var builder = new System.Text.StringBuilder();
using ( XmlWriter writer = new NoNamespaceXmlWriter(new System.IO.StringWriter(builder)))
{
s2.Serialize(writer, o2, ns2);
}
Console.WriteLine("{0}",builder.ToString());
The XmlTextWriter is sort of broken, though. According to the reference doc, when it writes it does not check for the following:
Invalid characters in attribute and element names.
Unicode characters that do not fit the specified encoding. If the Unicode
characters do not fit the specified
encoding, the XmlTextWriter does not
escape the Unicode characters into
character entities.
Duplicate attributes.
Characters in the DOCTYPE public
identifier or system identifier.
These problems with XmlTextWriter have been around since v1.1 of the .NET Framework, and they will remain, for backward compatibility. If you have no concerns about those problems, then by all means use the XmlTextWriter. But most people would like a bit more reliability.
To get that, while still suppressing namespaces during serialization, instead of deriving from XmlTextWriter, define a concrete implementation of the abstract XmlWriter and its 24 methods.
An example is here:
public class XmlWriterWrapper : XmlWriter
{
protected XmlWriter writer;
public XmlWriterWrapper(XmlWriter baseWriter)
{
this.Writer = baseWriter;
}
public override void Close()
{
this.writer.Close();
}
protected override void Dispose(bool disposing)
{
((IDisposable) this.writer).Dispose();
}
public override void Flush()
{
this.writer.Flush();
}
public override string LookupPrefix(string ns)
{
return this.writer.LookupPrefix(ns);
}
public override void WriteBase64(byte[] buffer, int index, int count)
{
this.writer.WriteBase64(buffer, index, count);
}
public override void WriteCData(string text)
{
this.writer.WriteCData(text);
}
public override void WriteCharEntity(char ch)
{
this.writer.WriteCharEntity(ch);
}
public override void WriteChars(char[] buffer, int index, int count)
{
this.writer.WriteChars(buffer, index, count);
}
public override void WriteComment(string text)
{
this.writer.WriteComment(text);
}
public override void WriteDocType(string name, string pubid, string sysid, string subset)
{
this.writer.WriteDocType(name, pubid, sysid, subset);
}
public override void WriteEndAttribute()
{
this.writer.WriteEndAttribute();
}
public override void WriteEndDocument()
{
this.writer.WriteEndDocument();
}
public override void WriteEndElement()
{
this.writer.WriteEndElement();
}
public override void WriteEntityRef(string name)
{
this.writer.WriteEntityRef(name);
}
public override void WriteFullEndElement()
{
this.writer.WriteFullEndElement();
}
public override void WriteProcessingInstruction(string name, string text)
{
this.writer.WriteProcessingInstruction(name, text);
}
public override void WriteRaw(string data)
{
this.writer.WriteRaw(data);
}
public override void WriteRaw(char[] buffer, int index, int count)
{
this.writer.WriteRaw(buffer, index, count);
}
public override void WriteStartAttribute(string prefix, string localName, string ns)
{
this.writer.WriteStartAttribute(prefix, localName, ns);
}
public override void WriteStartDocument()
{
this.writer.WriteStartDocument();
}
public override void WriteStartDocument(bool standalone)
{
this.writer.WriteStartDocument(standalone);
}
public override void WriteStartElement(string prefix, string localName, string ns)
{
this.writer.WriteStartElement(prefix, localName, ns);
}
public override void WriteString(string text)
{
this.writer.WriteString(text);
}
public override void WriteSurrogateCharEntity(char lowChar, char highChar)
{
this.writer.WriteSurrogateCharEntity(lowChar, highChar);
}
public override void WriteValue(bool value)
{
this.writer.WriteValue(value);
}
public override void WriteValue(DateTime value)
{
this.writer.WriteValue(value);
}
public override void WriteValue(decimal value)
{
this.writer.WriteValue(value);
}
public override void WriteValue(double value)
{
this.writer.WriteValue(value);
}
public override void WriteValue(int value)
{
this.writer.WriteValue(value);
}
public override void WriteValue(long value)
{
this.writer.WriteValue(value);
}
public override void WriteValue(object value)
{
this.writer.WriteValue(value);
}
public override void WriteValue(float value)
{
this.writer.WriteValue(value);
}
public override void WriteValue(string value)
{
this.writer.WriteValue(value);
}
public override void WriteWhitespace(string ws)
{
this.writer.WriteWhitespace(ws);
}
public override XmlWriterSettings Settings
{
get
{
return this.writer.Settings;
}
}
protected XmlWriter Writer
{
get
{
return this.writer;
}
set
{
this.writer = value;
}
}
public override System.Xml.WriteState WriteState
{
get
{
return this.writer.WriteState;
}
}
public override string XmlLang
{
get
{
return this.writer.XmlLang;
}
}
public override System.Xml.XmlSpace XmlSpace
{
get
{
return this.writer.XmlSpace;
}
}
}
Then, provide a derived class that overrides the StartElement method, as before:
public class NamespaceSupressingXmlWriter : XmlWriterWrapper
{
//Provide as many contructors as you need
public NamespaceSupressingXmlWriter(System.IO.TextWriter output)
: base(XmlWriter.Create(output)) { }
public NamespaceSupressingXmlWriter(XmlWriter output)
: base(XmlWriter.Create(output)) { }
public override void WriteStartElement(string prefix, string localName, string ns)
{
base.WriteStartElement("", localName, "");
}
}
And then use this writer like so:
var o2= new MyTypeWithNamespaces { ..intializers.. };
var builder = new System.Text.StringBuilder();
var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
using ( XmlWriter innerWriter = XmlWriter.Create(builder, settings))
using ( XmlWriter writer = new NamespaceSupressingXmlWriter(innerWriter))
{
s2.Serialize(writer, o2, ns2);
}
Console.WriteLine("{0}",builder.ToString());
Credit for this to Oleg Tkachenko.
After reading Microsoft's documentation and several solutions online, I have discovered the solution to this problem. It works with both the built-in XmlSerializer and custom XML serialization via IXmlSerialiazble.
To wit, I'll use the same MyTypeWithNamespaces XML sample that's been used in the answers to this question so far.
[XmlRoot("MyTypeWithNamespaces", Namespace="urn:Abracadabra", IsNullable=false)]
public class MyTypeWithNamespaces
{
// As noted below, per Microsoft's documentation, if the class exposes a public
// member of type XmlSerializerNamespaces decorated with the
// XmlNamespacesDeclarationAttribute, then the XmlSerializer will utilize those
// namespaces during serialization.
public MyTypeWithNamespaces( )
{
this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
// Don't do this!! Microsoft's documentation explicitly says it's not supported.
// It doesn't throw any exceptions, but in my testing, it didn't always work.
// new XmlQualifiedName(string.Empty, string.Empty), // And don't do this:
// new XmlQualifiedName("", "")
// DO THIS:
new XmlQualifiedName(string.Empty, "urn:Abracadabra") // Default Namespace
// Add any other namespaces, with prefixes, here.
});
}
// If you have other constructors, make sure to call the default constructor.
public MyTypeWithNamespaces(string label, int epoch) : this( )
{
this._label = label;
this._epoch = epoch;
}
// An element with a declared namespace different than the namespace
// of the enclosing type.
[XmlElement(Namespace="urn:Whoohoo")]
public string Label
{
get { return this._label; }
set { this._label = value; }
}
private string _label;
// An element whose tag will be the same name as the property name.
// Also, this element will inherit the namespace of the enclosing type.
public int Epoch
{
get { return this._epoch; }
set { this._epoch = value; }
}
private int _epoch;
// Per Microsoft's documentation, you can add some public member that
// returns a XmlSerializerNamespaces object. They use a public field,
// but that's sloppy. So I'll use a private backed-field with a public
// getter property. Also, per the documentation, for this to work with
// the XmlSerializer, decorate it with the XmlNamespaceDeclarations
// attribute.
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces Namespaces
{
get { return this._namespaces; }
}
private XmlSerializerNamespaces _namespaces;
}
That's all to this class. Now, some objected to having an XmlSerializerNamespaces object somewhere within their classes; but as you can see, I neatly tucked it away in the default constructor and exposed a public property to return the namespaces.
Now, when it comes time to serialize the class, you would use the following code:
MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel", 42);
/******
OK, I just figured I could do this to make the code shorter, so I commented out the
below and replaced it with what follows:
// You have to use this constructor in order for the root element to have the right namespaces.
// If you need to do custom serialization of inner objects, you can use a shortened constructor.
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces), new XmlAttributeOverrides(),
new Type[]{}, new XmlRootAttribute("MyTypeWithNamespaces"), "urn:Abracadabra");
******/
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),
new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" });
// I'll use a MemoryStream as my backing store.
MemoryStream ms = new MemoryStream();
// This is extra! If you want to change the settings for the XmlSerializer, you have to create
// a separate XmlWriterSettings object and use the XmlTextWriter.Create(...) factory method.
// So, in this case, I want to omit the XML declaration.
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Encoding = Encoding.UTF8; // This is probably the default
// You could use the XmlWriterSetting to set indenting and new line options, but the
// XmlTextWriter class has a much easier method to accomplish that.
// The factory method returns a XmlWriter, not a XmlTextWriter, so cast it.
XmlTextWriter xtw = (XmlTextWriter)XmlTextWriter.Create(ms, xws);
// Then we can set our indenting options (this is, of course, optional).
xtw.Formatting = Formatting.Indented;
// Now serialize our object.
xs.Serialize(xtw, myType, myType.Namespaces);
Once you have done this, you should get the following output:
<MyTypeWithNamespaces>
<Label xmlns="urn:Whoohoo">myLabel</Label>
<Epoch>42</Epoch>
</MyTypeWithNamespaces>
I have successfully used this method in a recent project with a deep hierachy of classes that are serialized to XML for web service calls. Microsoft's documentation is not very clear about what to do with the publicly accesible XmlSerializerNamespaces member once you've created it, and so many think it's useless. But by following their documentation and using it in the manner shown above, you can customize how the XmlSerializer generates XML for your classes without resorting to unsupported behavior or "rolling your own" serialization by implementing IXmlSerializable.
It is my hope that this answer will put to rest, once and for all, how to get rid of the standard xsi and xsd namespaces generated by the XmlSerializer.
UPDATE: I just want to make sure I answered the OP's question about removing all namespaces. My code above will work for this; let me show you how. Now, in the example above, you really can't get rid of all namespaces (because there are two namespaces in use). Somewhere in your XML document, you're going to need to have something like xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. If the class in the example is part of a larger document, then somewhere above a namespace must be declared for either one of (or both) Abracadbra and Whoohoo. If not, then the element in one or both of the namespaces must be decorated with a prefix of some sort (you can't have two default namespaces, right?). So, for this example, Abracadabra is the defalt namespace. I could inside my MyTypeWithNamespaces class add a namespace prefix for the Whoohoo namespace like so:
public MyTypeWithNamespaces
{
this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
new XmlQualifiedName(string.Empty, "urn:Abracadabra"), // Default Namespace
new XmlQualifiedName("w", "urn:Whoohoo")
});
}
Now, in my class definition, I indicated that the <Label/> element is in the namespace "urn:Whoohoo", so I don't need to do anything further. When I now serialize the class using my above serialization code unchanged, this is the output:
<MyTypeWithNamespaces xmlns:w="urn:Whoohoo">
<w:Label>myLabel</w:Label>
<Epoch>42</Epoch>
</MyTypeWithNamespaces>
Because <Label> is in a different namespace from the rest of the document, it must, in someway, be "decorated" with a namespace. Notice that there are still no xsi and xsd namespaces.
XmlSerializer sr = new XmlSerializer(objectToSerialize.GetType());
TextWriter xmlWriter = new StreamWriter(filename);
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
sr.Serialize(xmlWriter, objectToSerialize, namespaces);
This is the first of my two answers to the question.
If you want fine control over the namespaces - for example if you want to omit some of them but not others, or if you want to replace one namespace with another, you can do this using XmlAttributeOverrides.
Suppose you have this type definition:
// explicitly specify a namespace for this type,
// to be used during XML serialization.
[XmlRoot(Namespace="urn:Abracadabra")]
public class MyTypeWithNamespaces
{
// private fields backing the properties
private int _Epoch;
private string _Label;
// explicitly define a distinct namespace for this element
[XmlElement(Namespace="urn:Whoohoo")]
public string Label
{
set { _Label= value; }
get { return _Label; }
}
// this property will be implicitly serialized to XML using the
// member name for the element name, and inheriting the namespace from
// the type.
public int Epoch
{
set { _Epoch= value; }
get { return _Epoch; }
}
}
And this serialization pseudo-code:
var o2= new MyTypeWithNamespaces() { ..initializers...};
ns.Add( "", "urn:Abracadabra" );
XmlSerializer s2 = new XmlSerializer(typeof(MyTypeWithNamespaces));
s2.Serialize(System.Console.Out, o2, ns);
You would get something like this XML:
<MyTypeWithNamespaces xmlns="urn:Abracadabra">
<Label xmlns="urn:Whoohoo">Cimsswybclaeqjh</Label>
<Epoch>97</Epoch>
</MyTypeWithNamespaces>
Notice that there is a default namespace on the root element, and there is also a distinct namespace on the "Label" element. These namespaces were dictated by the attributes decorating the type, in the code above.
The Xml Serialization framework in .NET includes the possibility to explicitly override the attributes that decorate the actual code. You do this with the XmlAttributesOverrides class and friends. Suppose I have the same type, and I serialize it this way:
// instantiate the container for all attribute overrides
XmlAttributeOverrides xOver = new XmlAttributeOverrides();
// define a set of XML attributes to apply to the root element
XmlAttributes xAttrs1 = new XmlAttributes();
// define an XmlRoot element (as if [XmlRoot] had decorated the type)
// The namespace in the attribute override is the empty string.
XmlRootAttribute xRoot = new XmlRootAttribute() { Namespace = ""};
// add that XmlRoot element to the container of attributes
xAttrs1.XmlRoot= xRoot;
// add that bunch of attributes to the container holding all overrides
xOver.Add(typeof(MyTypeWithNamespaces), xAttrs1);
// create another set of XML Attributes
XmlAttributes xAttrs2 = new XmlAttributes();
// define an XmlElement attribute, for a type of "String", with no namespace
var xElt = new XmlElementAttribute(typeof(String)) { Namespace = ""};
// add that XmlElement attribute to the 2nd bunch of attributes
xAttrs2.XmlElements.Add(xElt);
// add that bunch of attributes to the container for the type, and
// specifically apply that bunch to the "Label" property on the type.
xOver.Add(typeof(MyTypeWithNamespaces), "Label", xAttrs2);
// instantiate a serializer with the overrides
XmlSerializer s3 = new XmlSerializer(typeof(MyTypeWithNamespaces), xOver);
// serialize
s3.Serialize(System.Console.Out, o2, ns2);
The result looks like this;
<MyTypeWithNamespaces>
<Label>Cimsswybclaeqjh</Label>
<Epoch>97</Epoch>
</MyTypeWithNamespaces>
You have stripped the namespaces.
A logical question is, can you strip all namespaces from arbitrary types during serialization, without going through the explicit overrides? The answer is YES, and how to do it is in my next response.
Related
I have swt text where in I have written like "new AutoCompleteField (textSearch,new TextContentProvider(), searchList); it works but it finds the strings start with expression. I want to create my own proposal provider where i can write something if my string contains any keyword, i should get autoComplete popup.
You can't use the existing AutoCompleteField for this since you need to change the content proposal provider.
A suitable IContentProposalProvider would be something like:
public class AnyPositionContentProposalProvider implements IContentProposalProvider
{
private final String [] proposals;
public AnyPositionContentProposalProvider(String [] theProposals)
{
proposals = theProposals;
}
#Override
public IContentProposal [] getProposals(String contents, int position)
{
List<IContentProposal> result = new ArrayList<>();
for (String proposal : proposals) {
if (proposal.contains(contents)) {
result.add(new ContentProposal(proposal));
}
}
return result.toArray(new IContentProposal [result.size()]);
}
}
The following methods set this up to work like AutoCompleteField:
// Installs on a Text control
public static void installAnyPositionMatch(Text control, String [] proposals)
{
installAnyPositionMatch(control, new TextContentAdapter(), proposals);
}
// Install on any control with a content adapter
public static void installAnyPositionMatch(Control control, IControlContentAdapter controlContentAdapter, String [] proposals)
{
IContentProposalProvider proposalProvider = new AnyPositionContentProposalProvider(proposals);
ContentProposalAdapter adapter = new ContentProposalAdapter(control, controlContentAdapter, proposalProvider, null, null);
adapter.setPropagateKeys(true);
adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
}
I'm working with EF 4.5 and DbContext. At business rules layer level, I should implement checks to avoid change entity value properties in some entity scenarios. Sample: StartProjecteDate should be readonly if ProjectIsStarted but not in other status.
I follow DRY principle, for this reason, I should be able to inspect readonly properties list from context and also from UI.
My question:
Is there a DataAnnotation validator that can dynamically set properties as readonly?
(and if not, is there a different / better solution to this problem?)
Notice than I'm working with Web Forms (and Telerik) architecture, a clean and elegant pattern will be welcome.
I'm trying to set and get at run time EditableAttribute as Jesse Webb explains, but I'm not able to get dataannotation attributes from property, my code:
<EditableAttribute(False)>
<MaxLength(400, ErrorMessage:="Màxim 400 caracters")>
Public Property NomInvertebrat As String
Edited Nov 8 2013 after digging docs, it seems that dataanottions if for class but for instance object itself. Perhaps an iReadonlyableProperties interface may be a way.
I have a class containing extension methods that lets me read data annotations like this:
int maxRefLen = ReflectionAPI.GetProperty<Organisation, String>(x => x.Name)
.GetAttribute<StringLengthAttribute>()
.GetValueOrDefault(x => x.MaximumLength, 256);
So if you use it you should be able to do get the value of the EditableAttribute like this:
bool isEditable = ReflectionAPI.GetProperty<Foo, String>(x => x.NomInvertebrat)
.GetAttribute<EditableAttribute>()
.GetValueOrDefault(x => x.AllowEdit, true);
As for setting the data annotations at run-time, I haven't done it myself but I have read that there is a solution here: Setting data-annotations at runtime
Getting a list of all data annotations of a particular type I think would entail reading the entity framework metadata. Again I haven't tried this.
If you add that together I personally think it feels clunky rather than elegant, but you have asked for a solution using DataAnnotations and something more elegant would probably mean getting into your architecture.
I would be inclined to do this:
public bool StartDateIsReadOnly
{
//use this property client-side to disable the input
get{ return Project.IsStarted;}
}
//Implement IValidatable object to do server side validation
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext
{
bool startdateIsChanged = // I'll leave you to work out this bit
var results = new List<ValidationResult>();
if(StartDateIsReadOnly && startdateIsChanged)
results.Add(new ValidationResult("Start Date cannot be changed after project is started");
}
Here is the ReflectionAPI class:
Please note that the class includes part of a hack that #JonSkeet posted and described as "evil". I personally think this bit ain't so bad, but you should read the following references:
Override a generic method for value types and reference types.
Evil code - overload resolution workaround
public static class ReflectionAPI
{
public static int GetValueOrDefault<TInput>(this TInput a, Func<TInput, int> func, int defaultValue)
where TInput : Attribute
//Have to restrict to struct or you get the error:
//The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'
{
if (a == null)
return defaultValue;
return func(a);
}
public static Nullable<TResult> GetValueOrDefault<TInput, TResult>(this TInput a, Func<TInput, TResult> func, Nullable<TResult> defaultValue)
where TInput : Attribute
where TResult : struct
//Have to restrict to struct or you get the error:
//The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'
{
if (a == null)
return defaultValue;
return func(a);
}
//In order to constrain to a class without interfering with the overload that has a generic struct constraint
//we need to add a parameter to the signature that is a reference type restricted to a class
public class ClassConstraintHack<T> where T : class { }
//The hack means we have an unused parameter in the signature
//http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx
public static TResult GetValueOrDefault<TInput, TResult>(this TInput a, Func<TInput, TResult> func, TResult defaultValue, ClassConstraintHack<TResult> ignored = default(ClassConstraintHack<TResult>))
where TInput : Attribute
where TResult : class
{
if (a == null)
return defaultValue;
return func(a);
}
//I don't go so far as to use the inheritance trick decribed in the evil code overload resolution blog,
//just create some overloads that take nullable types - and I will just keep adding overloads for other nullable type
public static bool? GetValueOrDefault<TInput>(this TInput a, Func<TInput, bool?> func, bool? defaultValue)
where TInput : Attribute
{
if (a == null)
return defaultValue;
return func(a);
}
public static int? GetValueOrDefault<TInput>(this TInput a, Func<TInput, int?> func, int? defaultValue)
where TInput : Attribute
{
if (a == null)
return defaultValue;
return func(a);
}
public static T GetAttribute<T>(this PropertyInfo p) where T : Attribute
{
if (p == null)
return null;
return p.GetCustomAttributes(false).OfType<T>().LastOrDefault();
}
public static PropertyInfo GetProperty<T, R>(Expression<Func<T, R>> expression)
{
if (expression == null)
return null;
MemberExpression memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
return null;
return memberExpression.Member as PropertyInfo;
}
}
.NET allows you to dynamically change structure of Class by implementing System.ComponentModel.ICustomTypeDescriptor. Most serializers support this interface.
// Sample Serialization
foreach(PropertyDescriptor p in TypeDescriptor.GetProperties(obj)){
string name = p.PropertyName;
object value = p.GetValue(obj);
}
Internally TypeDescriptor uses Reflection, but the implementation allows us to override reflection attributes easily.
Here are three steps of implementation,
// Implement System.ComponentModel.ICustomTypeDescriptor Interface on
// your Entity
public class MyEntity: System.ComponentModel.ICustomTypeDescriptor
{
....
// most methods needs only call to default implementation as shown below
System.ComponentModel.AttributeCollection
System.ComponentModel.ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
}
string System.ComponentModel.ICustomTypeDescriptor.GetClassName()
{
return TypeDescriptor.GetClassName(this, true);
}
string System.ComponentModel.ICustomTypeDescriptor.GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}
System.ComponentModel.TypeConverter System.ComponentModel.ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
System.ComponentModel.EventDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
System.ComponentModel.PropertyDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(this, true);
}
object System.ComponentModel.ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this, editorBaseType, true);
}
System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(this, attributes, true);
}
System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents()
{
return TypeDescriptor.GetEvents(this, true);
}
System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
return TypeDescriptor.GetProperties(this, attributes, true);
}
object System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd)
{
return this;
}
// The Only method that needs different implementation is below
System.ComponentModel.PropertyDescriptorCollection
System.ComponentModel.ICustomTypeDescriptor.GetProperties()
{
// ... you are supposed to create new instance of
// PropertyDescriptorCollection with PropertyDescriptor
PropertyDescriptorCollection pdc = new PropertyDescriptorCollection();
foreach(PropertyDescriptor p in TypeDescriptor.GetProperties(this,true)){
// if readonly..
AtomPropertyDescriptor ap = new AtomPropertyDescriptor(p, p.Name);
// or
AtomPropertyDescriptor ap = new AtomPropertyDescriptor(p, p.Name,
true,
new XmlIgnoreAttribute(),
new ScriptIgnoreAttribute(),
new ReadOnlyAttribute());
pdc.Add(ap);
}
return pdc;
}
}
// And here is the AtomPropertyDescriptorClass
public class AtomPropertyDescriptor : PropertyDescriptor
{
PropertyDescriptor desc;
bool? readOnly = null;
public AtomPropertyDescriptor(PropertyDescriptor pd, string name,
bool? readOnly, params Attribute[] attrs) :
base(name, attrs)
{
desc = pd;
this.readOnly = readOnly;
}
public override bool CanResetValue(object component)
{
return desc.CanResetValue(component);
}
public override Type ComponentType
{
get
{
return desc.ComponentType;
}
}
public override object GetValue(object component)
{
return desc.GetValue(component);
}
public override bool IsReadOnly
{
get
{
if (readOnly.HasValue)
return readOnly.Value;
return desc.IsReadOnly;
}
}
public override Type PropertyType
{
get { return desc.PropertyType; }
}
public override void ResetValue(object component)
{
desc.ResetValue(component);
}
public override void SetValue(object component, object value)
{
desc.SetValue(component, value);
}
public override bool ShouldSerializeValue(object component)
{
return desc.ShouldSerializeValue(component);
}
}
I think what you are looking for is a custom Annotation Attribute like this:
<DisableEditAttribute(this.IsProjectStarted)>
Public Property NomInvertebrat As String
public override bool IsValid(bool value)
{
bool result = true;
// Add validation logic here.
if(value)
{
//Compare Current Value Against DB Value.
}
return result;
}
See MSDN: http://msdn.microsoft.com/en-us/library/cc668224(v=vs.98).aspx
I am using aspectj to add some field to a existing class and annotate it also.
I am using load time weaving .
Example :- I have a Class customer in which i am adding 3 string attributes. But my issues is that I have to set some values and get it also before my business call.
I am trying the below approach.
In my aj file i have added the below, my problem is in the Around pointcut , how do i get the attribute and set the attribute.
public String net.customers.PersonCustomer.getOfflineRiskCategory() {
return OfflineRiskCategory;
}
public void net.customers.PersonCustomer.setOfflineRiskCategory(String offlineRiskCategory) {
OfflineRiskCategory = offlineRiskCategory;
}
public String net.customers.PersonCustomer.getOnlineRiskCategory() {
return OnlineRiskCategory;
}
public void net.customers.PersonCustomer.setOnlineRiskCategory(String onlineRiskCategory) {
OnlineRiskCategory = onlineRiskCategory;
}
public String net.customers.PersonCustomer.getPersonCommercialStatus() {
return PersonCommercialStatus;
}
public void net.customers.PersonCustomer.setPersonCommercialStatus(String personCommercialStatus) {
PersonCommercialStatus = personCommercialStatus;
}
#Around("execution(* net.xxx.xxx.xxx.DataMigration.populateMap(..))")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
Object arguments[] = joinPoint.getArgs();
if (arguments != null) {
HashMap<String, String> hMap = (HashMap) arguments[0];
PersonCustomer cus = (PersonCustomer) arguments[1];
return joinPoint.proceed();
}
If anyone has ideas please let me know.
regards,
FT
First suggestion, I would avoid mixing code-style aspectj with annotation-style. Ie- instead of #Around, use around.
Second, instead of getting the arguments from the joinPoint, you should bind them in the pointcut:
Object around(Map map, PersonCustomer cust) :
execution(* net.xxx.xxx.xxx.DataMigration.populateMap(Map, PersonCustomer) && args(map, cust) {
...
return proceed(map, cust);
}
Now, to answer your question: you also need to use intertype declarations to add new fields to your class, so do something like this:
private String net.customers.PersonCustomer.OfflineRiskCategory;
private String net.customers.PersonCustomer.OnlineRiskCategory;
private String net.customers.PersonCustomer.PersonCommercialStatus;
Note that the private keyword here means private to the aspect, not to the class that you declare it on.
I am currently examining Moles from the outside while I wait for my VS 2010 license, and I wonder whether Moles allows me to:
provide the ability to assígn multiple mole delegates for a method being moled, perhaps at a test fixture setup level?
switch in runtime in my test case, which of my mole delegates must be invoked for the upcoming call(s) to the moled method being isolated?
Any hints?
Best Answer:
It is much easier and makes far more sense to include gating logic in the detour method, than using two stubs for the same method! For example, MyMethod reads data from three different files on disk, each requiring different mock data to be returned. We may detour System.IO.File.OpenRead and gate the return value by analyzing the input parameters of OpenRead:
TEST METHOD:
[TestMethod]
[HostType("Moles")]
public void Test()
{
System.IO.Moles.MFile.OpenReadString = filePath => {
var mockStream = new System.IO.FileStream();
byte[] buffer;
switch (filePath)
{
case #"C:\DataFile.dat":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
case #"C:\TextFile.txt":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
case #"C:\LogFile.log":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
}
return mockStream;
};
var target = new MyClass();
target.MyMethod();
}
TARGET TYPE:
using System.IO;
public class MyClass
{
public void MyMethod()
{
var fileAData = File.OpenRead(#"C:\DataFile.dat");
var fileBData = File.OpenRead(#"C:\TextFile.txt");
var fileCData = File.OpenRead(#"C:\LogFile.log");
}
}
Direct Answer to Your Questions:
Yes to #1: instantiate one type for each detour, and then use each for the desired behavior. And, yes to #2: act upon one instance of the mole type or the other. This requires addition of method input parameters or class constructor injection.
For example, MyMethod reads three data files from disk, and you need to pass back three different data mocks. MyMethod requires three parameters, an overtly intrusive solution. (Note input parameters are FileInfo type; because, System.IO>File is static and can not be instantiated: For example:
TEST METHOD:
[TestMethod]
[HostType("Moles")]
public void Test()
{
var fileInfoMoleA = new System.IO.Moles.MFileInfo();
fileInfoMoleA.OpenRead = () => { return new FileStream(); };
var fileInfoMoleB = new System.IO.Moles.MFileInfo();
fileInfoMoleB.OpenRead = () => { return new FileStream(); };
var fileInfoMoleC = new System.IO.Moles.MFileInfo();
fileInfoMoleC.OpenRead = () => { return new FileStream(); };
var target = new MyClass();
target.MyMethod(fileInfoMoleA, fileInfoMoleB, fileInfoMoleC);
}
TARGET TYPE:
using System.IO;
public class MyClass
{
// Input parameters are FileInfo type; because, System.IO.File
// is a static class, and can not be instantiated.
public void MyMethod(FileInfo fileInfoA, FileInfo fileInfoB, FileInfo fileInfoC)
{
var fileAData = fileInfoA.OpenRead();
var fileBData = fileInfoB.OpenRead();
var fileCData = fileInfoC.OpenRead();
}
}
UPDATE:
In response to #Chai comment, it is possible to create common methods, within the test project, that may be referenced as the mole detour delegate. For example, you may wish to write a common method that may be referenced by any unit test, that sets up a variety of pre-configured scenarios. The following example displays how a parameterized method could be used. Get creative -- they're just method calls!
TARGET TYPES:
namespace PexMoleDemo
{
public class MyClass
{
private MyMath _math;
public MyClass()
{
_math = new MyMath() { left = 1m, right = 2m };
}
public decimal GetResults()
{
return _math.Divide();
}
}
public class MyOtherClass
{
private MyMath _math;
public MyOtherClass()
{
_math = new MyMath() { left = 100m, right = 200m };
}
public decimal Divide()
{
return _math.Divide();
}
}
public class MyMath
{
public decimal left { get; set; }
public decimal right { get; set; }
public decimal Divide()
{
return left / right;
}
}
}
TEST METHODS:
ArrangeScenarios() sets up mole detours, by switching on the enumeration parameter. This allows the same scenarios to be erected, in a DRY manner, throughout many tests.
using System;
using Microsoft.Moles.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PexMoleDemo;
[assembly: MoledAssembly("PexMoleDemo")]
namespace TestProject1
{
[TestClass()]
public class ProgramTest
{
public enum Scenarios
{
DivideByZero,
MultiplyInsteadOfDivide
}
private void ArrangeScenario(Scenarios scenario)
{
switch (scenario)
{
case Scenarios.DivideByZero:
PexMoleDemo.Moles.MMyMath.AllInstances.rightGet =
instance => { return 0m; };
break;
case Scenarios.MultiplyInsteadOfDivide:
PexMoleDemo.Moles.MMyMath.AllInstances.Divide =
instance => { return instance.left * instance.right; };
break;
default:
throw new NotImplementedException("Invalid scenario.");
}
}
[TestMethod]
[HostType("Moles")]
[ExpectedException(typeof(DivideByZeroException))]
public void Test1()
{
ArrangeScenario(Scenarios.DivideByZero);
var target = new PexMoleDemo.MyClass();
var math = new PexMoleDemo.MyMath() { left = 1, right = 2 };
var left = math.left;
var right = math.right;
var actual = target.GetResults();
}
[TestMethod]
[HostType("Moles")]
public void Test2()
{
ArrangeScenario(Scenarios.MultiplyInsteadOfDivide);
// Perform some sort of test that determines if code breaks
// when values are multiplied instead of divided.
}
[TestMethod]
[HostType("Moles")]
[ExpectedException(typeof(DivideByZeroException))]
public void Test3()
{
ArrangeScenario(Scenarios.DivideByZero);
var target = new PexMoleDemo.MyOtherClass();
var math = new PexMoleDemo.MyMath() { left = 1, right = 2 };
var left = math.left;
var right = math.right;
var actual = target.Divide();
}
[TestMethod]
[HostType("Moles")]
public void Test4()
{
ArrangeScenario(Scenarios.MultiplyInsteadOfDivide);
// Perform some sort of test that determines if code breaks
// when values are multiplied instead of divided.
}
}
}
How would you refactor these two classes to abstract out the similarities? An abstract class? Simple inheritance? What would the refactored class(es) look like?
public class LanguageCode
{
/// <summary>
/// Get the lowercase two-character ISO 639-1 language code.
/// </summary>
public readonly string Value;
public LanguageCode(string language)
{
this.Value = new CultureInfo(language).TwoLetterISOLanguageName;
}
public static LanguageCode TryParse(string language)
{
if (language == null)
{
return null;
}
if (language.Length > 2)
{
language = language.Substring(0, 2);
}
try
{
return new LanguageCode(language);
}
catch (ArgumentException)
{
return null;
}
}
}
public class RegionCode
{
/// <summary>
/// Get the uppercase two-character ISO 3166 region/country code.
/// </summary>
public readonly string Value;
public RegionCode(string region)
{
this.Value = new RegionInfo(region).TwoLetterISORegionName;
}
public static RegionCode TryParse(string region)
{
if (region == null)
{
return null;
}
if (region.Length > 2)
{
region = region.Substring(0, 2);
}
try
{
return new RegionCode(region);
}
catch (ArgumentException)
{
return null;
}
}
}
It depends, if they are not going to do much more, then I would probably leave them as is - IMHO factoring out stuff is likely to be more complex, in this case.
Unless you have a strong reason for refactoring (because you are going to add more classes like those in near future) the penalty of changing the design for such a small and contrived example would overcome the gain in maintenance or overhead in this scenario. Anyhow here is a possible design based on generic and lambda expressions.
public class TwoLetterCode<T>
{
private readonly string value;
public TwoLetterCode(string value, Func<string, string> predicate)
{
this.value = predicate(value);
}
public static T TryParse(string value, Func<string, T> predicate)
{
if (value == null)
{
return default(T);
}
if (value.Length > 2)
{
value = value.Substring(0, 2);
}
try
{
return predicate(value);
}
catch (ArgumentException)
{
return default(T);
}
}
public string Value { get { return this.value; } }
}
public class LanguageCode : TwoLetterCode<LanguageCode> {
public LanguageCode(string language)
: base(language, v => new CultureInfo(v).TwoLetterISOLanguageName)
{
}
public static LanguageCode TryParse(string language)
{
return TwoLetterCode<LanguageCode>.TryParse(language, v => new LanguageCode(v));
}
}
public class RegionCode : TwoLetterCode<RegionCode>
{
public RegionCode(string language)
: base(language, v => new CultureInfo(v).TwoLetterISORegionName)
{
}
public static RegionCode TryParse(string language)
{
return TwoLetterCode<RegionCode>.TryParse(language, v => new RegionCode(v));
}
}
This is a rather simple question and to me smells awefully like a homework assignment.
You can obviously see the common bits in the code and I'm pretty sure you can make an attempt at it yourself by putting such things into a super-class.
You could maybe combine them into a Locale class, which stores both Language code and Region code, has accessors for Region and Language plus one parse function which also allows for strings like "en_gb"...
That's how I've seen locales be handled in various frameworks.
These two, as they stand, aren't going to refactor well because of the static methods.
You'd either end up with some kind of factory method on a base class that returns an a type of that base class (which would subsequently need casting) or you'd need some kind of additional helper class.
Given the amount of extra code and subsequent casting to the appropriate type, it's not worth it.
Create a generic base class (eg AbstractCode<T>)
add abstract methods like
protected T GetConstructor(string code);
override in base classes like
protected override RegionCode GetConstructor(string code)
{
return new RegionCode(code);
}
Finally, do the same with string GetIsoName(string code), eg
protected override GetIsoName(string code)
{
return new RegionCode(code).TowLetterISORegionName;
}
That will refactor the both. Chris Kimpton does raise the important question as to whether the effort is worth it.
I'm sure there is a better generics based solution. But still gave it a shot.
EDIT: As the comment says, static methods can't be overridden so one option would be to retain it and use TwoLetterCode objects around and cast them, but, as some other person has already pointed out, that is rather useless.
How about this?
public class TwoLetterCode {
public readonly string Value;
public static TwoLetterCode TryParseSt(string tlc) {
if (tlc == null)
{
return null;
}
if (tlc.Length > 2)
{
tlc = tlc.Substring(0, 2);
}
try
{
return new TwoLetterCode(tlc);
}
catch (ArgumentException)
{
return null;
}
}
}
//Likewise for Region
public class LanguageCode : TwoLetterCode {
public LanguageCode(string language)
{
this.Value = new CultureInfo(language).TwoLetterISOLanguageName;
}
public static LanguageCode TryParse(string language) {
return (LanguageCode)TwoLetterCode.TryParseSt(language);
}
}