Object serialization duplicating nodes - serialization

Can anyone tell me why my output is duplicating the 'FirstNode'?
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml.Serialization;
class Program
{
static void Main(string[] args)
{
Root root = new Root();
FirstNode firstNode = new FirstNode();
firstNode.Data = "DATA";
root.FirstNode.Add(firstNode);
XmlSerializer s = new XmlSerializer(typeof(Root));
StringWriter sw = new StringWriter();
s.Serialize(sw, root);
string serializedXml = sw.ToString();
Console.WriteLine(serializedXml);
Console.ReadKey();
}
}
public class Root
{
List<FirstNode> firstNode = new List<FirstNode>();
public List<FirstNode> FirstNode
{
get { return firstNode; }
set { firstNode = value; }
}
}
public class FirstNode
{
string data;
public string Data
{
get { return data; }
set { data = value; }
}
}
OUTPUT
<Root>
<FirstNode>
<FirstNode>
<Data>DATA</Data>
</FirstNode>
</FirstNode>
</Root>
Expected Output
<Root>
<FirstNode>
<Data>DATA</Data>
</FirstNode>
</Root>

Well if you look you have a Property Named FirstNode where you are storing your list, and inside the List you are storing FirstNode object...
If you want to see it just change the name of the property FirstNode in the class Root to Nodes and you will see a differnet output
<Root>
<Nodes>
<FirstNode>
<Data>DATA</Data>
</FirstNode>
</Nodes>
</Root>
The Root tag appears because is the Object Type, as well as the FirsNode , then you have tags like Data and Nodes( in my case) because are the serialized properties of these classes

Think it is this line:
root.FirstNode.Add(firstNode);
You are adding a first node to a first node and therefore getting two layers of first node.

You want:
[XmlElement("FirstNode")]
public List<FirstNode> FirstNode
{
get { return firstNode; }
set { firstNode = value; }
}
This will only add <FirstNode> for the content items - not the list itself. You might also want to look at [XmlArray] / [XmlArrayItem] if you want finer control.

Related

RavenDB querying metadata

I want to prevent documents from being deleted in my project and I decided to use metadata to mark document as Archived. I used below code to do that:
public class DeleteDocumentListener : IDocumentDeleteListener
{
public void BeforeDelete(string key, object entityInstance, RavenJObject metadata)
{
metadata.Add("Archived", true);
throw new NotSupportedException();
}
}
After that I wanted to alter query to return only documents which have Archived metadata value set to false:
using (var session = _store.OpenSession())
{
var query = session.Advanced.DocumentQuery<Cutter>()
.WhereEquals("#metadata.Archived", false);
}
Unfortunately this query return empty result set. It occurs that if Document doesn't have this metadata property then above condition is treated as false. It wasn't what I expected.
How can I compose query to return Documents which don't have metadata property or this property has some value ?
You can solve it by creating an index for you Cutter documents and then query against that:
public class ArchivedIndex : AbstractIndexCreationTask<Cutter>
{
public class QueryModel
{
public bool Archived { get; set; }
}
public ArchivedIndex()
{
Map = documents => from doc in documents
select new QueryModel
{
Archived = MetadataFor(doc)["Archived"] != null && MetadataFor(doc).Value<bool>("Archived")
};
}
}
Then query it like this:
using (var session = documentStore.OpenSession())
{
var cutters = session.Query<ArchivedIndex.QueryModel, ArchivedIndex>()
.Where(x => x.Archived == false)
.OfType<Cutter>()
.ToList();
}
Hope this helps!
Quick side note. To create the index, the following code may need to be run:
new ArchivedIndex().Execute(session.Advanced.DocumentStore);

Unsupported Operation Exception mybatis

So in this code what I want is a random SQL query from the outside that will be loaded into a property file. As of now i've got the property file with a query in it to test this. So i would like some data out, with a headline and all the data beneath. Basically just the data to start with though, as this test should do. But I get the error message that i've linked below. I can't for the life of me figure out where my problem is. Help please! :)
I've got the following code;
DataHandler class.
public class DataHandler{
DataService dataService = new DataService();
public String getPropertyValue() throws IOException {
Properties prop = new Properties();
String propFileName = "randomSqlQuery.properties";
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
prop.load(inputStream);
if (inputStream == null) {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
String result = prop.getProperty("sqlQuery");
return result;
}
public Data getKeysAndValues() throws IOException {
String query = getPropertyValue();
List<List<Object>> randomSqlQuery = dataService.getRandomSqlQuery(query);
List<List<Object>> recordList = new ArrayList<>();
List<String> headline = new ArrayList();
if (randomSqlQuery != null && randomSqlQuery.size() > 0) {
{
List<Object> record = randomSqlQuery.get(0);
getHeadlines(record, headline);
}
for (int i = 1; i < randomSqlQuery.size(); i++) {
List<Object> singleRecord = randomSqlQuery.get(i);
recordList.add(singleRecord);
System.out.println(recordList);
}
}
return new DataImpl(headline, recordList);
}
private void getHeadlines(List<Object> record, List<String> headline) {
for (Object headlineName : record) {
headline.add((String) headlineName);
System.out.println(headlineName);
}
}
}
DataMapper class
public interface DataMapper {
public List<List<Object>> getRandomSqlQuery(#Param("query") String query);
}
DataMapper XML
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="nd.mappers.DataMapper">
<select id="getRandomSqlQuery" resultType="java.util.List">
${query}
</select>
</mapper>
DataImpl class, which has an interface connected to it
public class DataImpl implements Serializable, Data {
private final List<String> headers;
private final List<List<Object>> records;
public DataImpl(List<String> headers, List<List<Object>> records) {
this.headers = Collections.unmodifiableList(headers);
this.records = Collections.unmodifiableList(records);
}
#Override
public List<String> getHeaders() {
return this.headers;
}
#Override
public List<List<Object>> getRecords() {
return this.records;
}
}
And a DataService class
public class DataService implements DataMapper {
#Override
public List<List<Object>> getRandomSqlQuery(String query) {
SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();
try {
DataMapper dataMapper = sqlSession.getMapper(DataMapper.class);
return dataMapper.getRandomSqlQuery(query);
} finally {
sqlSession.close();
}
}
}
Finally the test
//dataHandler instantiated in top
#Test
public void getKeysAndValues() throws IOException {
dataHandler.getKeysAndValues();
}
And here is my error!
### Error querying database. Cause: java.lang.UnsupportedOperationException
### The error may exist in nd/mappers/DataMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT * FROM PERSON ### Cause: java.lang.UnsupportedOperationException
org.apache.ibatis.exceptions.PersistenceException
### Error querying database. Cause: java.lang.UnsupportedOperationException
### The error may exist in nd/mappers/DataMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT * FROM PERSON
### Cause: java.lang.UnsupportedOperationException
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:26)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:111)
No idea what to do. The SQL is coming from the property file. Sorry for massive text.
I just resolved the same error message. The problem lies here:
<select id="getRandomSqlQuery" resultType="Person">
${query}
</select>
The result type should not be a collection but a type that the
collection contains. In your case it should be some Person
POJO. This type then must be defined in the (say mybatis-config.xml) configuration
file:
<typeAliases>
<typeAlias alias="Person" type="com.example.bean.Book"/>
</typeAliases>
Also, you would want to check for null here:
try {
DataMapper dataMapper = qlSession.getMapper(DataMapper.class);
return dataMapper.getRandomSqlQuery(query);
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}

Web API Help pages - customizing Property documentation

I have my web api and I added the web api help pages to auto-generate my documentation. It's working great for methods where my parameters are listed out, but I have a method like this:
public SessionResult PostLogin(CreateSessionCommand request)
And, on my help page, it is only listing the command parameter in the properties section. However, in the sample request section, it lists out all of the properties of my CreateSessionCommand class.
Parameters
Name | Description | Additional information
request | No documentation available. | Define this parameter in the request body.
I would like it instead to list all of the properties in my CreateSessionCommand class. Is there an easy way to do this?
So, I managed to devise a workaround for this problem, in case anyone is interested.
In HelpPageConfigurationExtensions.cs I added the following extension method:
public static void AlterApiDescription(this ApiDescription apiDescription, HttpConfiguration config)
{
var docProvider = config.Services.GetDocumentationProvider();
var addParams = new List<ApiParameterDescription>();
var removeParams = new List<ApiParameterDescription>();
foreach (var param in apiDescription.ParameterDescriptions)
{
var type = param.ParameterDescriptor.ParameterType;
//string is some special case that is not a primitive type
//also, compare by full name because the type returned does not seem to match the types generated by typeof
bool isPrimitive = type.IsPrimitive || String.Compare(type.FullName, typeof(string).FullName) == 0;
if (!isPrimitive)
{
var properties = from p in param.ParameterDescriptor.ParameterType.GetProperties()
let s = p.SetMethod
where s.IsPublic
select p;
foreach (var property in properties)
{
var documentation = docProvider.GetDocumentation(new System.Web.Http.Controllers.ReflectedHttpParameterDescriptor()
{
ActionDescriptor = param.ParameterDescriptor.ActionDescriptor,
ParameterInfo = new CustomParameterInfo(property)
});
addParams.Add(new ApiParameterDescription()
{
Documentation = documentation,
Name = property.Name,
Source = ApiParameterSource.FromBody,
ParameterDescriptor = param.ParameterDescriptor
});
}
//since this is a complex type, select it to be removed from the api description
removeParams.Add(param);
}
}
//add in our new items
foreach (var item in addParams)
{
apiDescription.ParameterDescriptions.Add(item);
}
//remove the complex types
foreach (var item in removeParams)
{
apiDescription.ParameterDescriptions.Remove(item);
}
}
And here is the Parameter info instanced class I use
internal class CustomParameterInfo : ParameterInfo
{
public CustomParameterInfo(PropertyInfo prop)
{
base.NameImpl = prop.Name;
}
}
Then, we call the extension in another method inside the extensions class
public static HelpPageApiModel GetHelpPageApiModel(this HttpConfiguration config, string apiDescriptionId)
{
object model;
string modelId = ApiModelPrefix + apiDescriptionId;
if (!config.Properties.TryGetValue(modelId, out model))
{
Collection<ApiDescription> apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;
ApiDescription apiDescription = apiDescriptions.FirstOrDefault(api => String.Equals(api.GetFriendlyId(), apiDescriptionId, StringComparison.OrdinalIgnoreCase));
if (apiDescription != null)
{
apiDescription.AlterApiDescription(config);
HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
model = GenerateApiModel(apiDescription, sampleGenerator);
config.Properties.TryAdd(modelId, model);
}
}
return (HelpPageApiModel)model;
}
The comments that are used for this must be added to the controller method and not the properties of the class object. This might be because my object is part of an outside library
this should go as an addition to #Josh answer. If you want not only to list properties from the model class, but also include documentation for each property, Areas/HelpPage/XmlDocumentationProvider.cs file should be modified as follows:
public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
{
ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
if (reflectedParameterDescriptor != null)
{
if (reflectedParameterDescriptor.ParameterInfo is CustomParameterInfo)
{
const string PropertyExpression = "/doc/members/member[#name='P:{0}']";
var pi = (CustomParameterInfo) reflectedParameterDescriptor.ParameterInfo;
string selectExpression = String.Format(CultureInfo.InvariantCulture, PropertyExpression, pi.Prop.DeclaringType.FullName + "." + pi.Prop.Name);
XPathNavigator methodNode = _documentNavigator.SelectSingleNode(selectExpression);
if (methodNode != null)
{
return methodNode.Value.Trim();
}
}
else
{
XPathNavigator methodNode = GetMethodNode(reflectedParameterDescriptor.ActionDescriptor);
if (methodNode != null)
{
string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
XPathNavigator parameterNode = methodNode.SelectSingleNode(String.Format(CultureInfo.InvariantCulture, ParameterExpression, parameterName));
if (parameterNode != null)
{
return parameterNode.Value.Trim();
}
}
}
}
return null;
}
and CustomParameterInfo class should keep property info as well:
internal class CustomParameterInfo : ParameterInfo
{
public PropertyInfo Prop { get; private set; }
public CustomParameterInfo(PropertyInfo prop)
{
Prop = prop;
base.NameImpl = prop.Name;
}
}
This is currently not supported out of the box. Following bug is kind of related to that:
http://aspnetwebstack.codeplex.com/workitem/877

TextDecorationCollection serialization in WPF

Is there any xaml serialization attribute that I can specify for a dependency property which actually is a collection (TextDecorationCollection)?
I want to use serialization for cloning a very large and complex object. Here a sample of the code, simplified:
There is a MyVisualObject, that contains a lot of properties, including a custom font, which I want to clone
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class Export : Attribute
{
}
public class MyVisualObject : DependencyObject
{
[Export]
public CustomFont Font
{
get { return (CustomFont)GetValue(FontProperty); }
set { SetValue(FontProperty, value); }
}
// Using a DependencyProperty as the backing store for Font. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FontProperty =
DependencyProperty.Register("Font", typeof(CustomFont), typeof(MyVisualObject));
public MyVisualObject()
{
this.Font = new CustomFont();
}
}
And the custom font is defined like this:
public class CustomFont : DependencyObject
{
public TextDecorationCollection Decorations
{
get { return (TextDecorationCollection)GetValue(DecorationsProperty); }
set { SetValue(DecorationsProperty, value); }
}
// Using a DependencyProperty as the backing store for TextDecorations. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DecorationsProperty =
DependencyProperty.Register("Decorations", typeof(TextDecorationCollection), typeof(CustomFont), new UIPropertyMetadata(new TextDecorationCollection()));
public CustomFont()
{
this.Decorations = System.Windows.TextDecorations.Underline;
}
}
THe deep clone method:
public static T DeepClone<T>(T from)
{
object clone = Activator.CreateInstance(from.GetType());
Type t = from.GetType();
System.Reflection.PropertyInfo[] pinf = t.GetProperties();
foreach (PropertyInfo p in pinf)
{
bool serialize = false;
foreach (object temp in p.GetCustomAttributes(true))
{
if (temp is Export)
{
serialize = true;
}
}
if (serialize)
{
string xaml = XamlWriter.Save(p.GetValue(from, null));
XmlReader rd = XmlReader.Create(new StringReader(xaml));
p.SetValue(clone, XamlReader.Load(rd), null);
}
}
return (T)clone;
}
The problem is that each time I initialize the Decorations as Underline
this.Decorations = System.Windows.TextDecorations.Underline;
the cloning process crashes with this error:'Add value to collection of type 'System.Windows.TextDecorationCollection' threw an exception.' Line number '1' and line position '213'.
As far as I found out, the serialization, which is this part
string xaml = XamlWriter.Save(p.GetValue(from, null));
returns an xaml which does not have the decorations set as a collection:
<CustomFont xmlns="clr-namespace:WpfApplication1;assembly=WpfApplication1" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<CustomFont.Decorations>
<av:TextDecoration Location="Underline" />
</CustomFont.Decorations>
</CustomFont>
But the clone process would work if the xaml would be like this:
<CustomFont xmlns="clr-namespace:WpfApplication1;assembly=WpfApplication1" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<CustomFont.Decorations>
<av:TextDecorationCollection>
<av:TextDecoration Location="Underline" />
</av:TextDecorationCollection>
</CustomFont.Decorations>
</CustomFont>
I found a workaround, something with string replacements:
xaml = xaml.Replace("<CustomFont.Decorations><av:TextDecoration Location=\"Underline\" /></CustomFont.Decorations>", "<CustomFont.Decorations><av:TextDecorationCollection><av:TextDecoration Location=\"Underline\" /></av:TextDecorationCollection></CustomFont.Decorations>");
but I think it's really dirty, and I would apreciate it if you could provide a more clean solution (specifying an attribute for the Decorations property for example)
Have you tried applying the following attribute to the Decorations property:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

Duck type testing with C# 4 for dynamic objects

I'm wanting to have a simple duck typing example in C# using dynamic objects. It would seem to me, that a dynamic object should have HasValue/HasProperty/HasMethod methods with a single string parameter for the name of the value, property, or method you are looking for before trying to run against it. I'm trying to avoid try/catch blocks, and deeper reflection if possible. It just seems to be a common practice for duck typing in dynamic languages (JS, Ruby, Python etc.) that is to test for a property/method before trying to use it, then falling back to a default, or throwing a controlled exception. The example below is basically what I want to accomplish.
If the methods described above don't exist, does anyone have premade extension methods for dynamic that will do this?
Example: In JavaScript I can test for a method on an object fairly easily.
//JavaScript
function quack(duck) {
if (duck && typeof duck.quack === "function") {
return duck.quack();
}
return null; //nothing to return, not a duck
}
How would I do the same in C#?
//C# 4
dynamic Quack(dynamic duck)
{
//how do I test that the duck is not null,
//and has a quack method?
//if it doesn't quack, return null
}
If you have control over all of the object types that you will be using dynamically, another option would be to force them to inherit from a subclass of the DynamicObject class that is tailored to not fail when a method that does not exist is invoked:
A quick and dirty version would look like this:
public class DynamicAnimal : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
bool success = base.TryInvokeMember(binder, args, out result);
// If the method didn't exist, ensure the result is null
if (!success) result = null;
// Always return true to avoid Exceptions being raised
return true;
}
}
You could then do the following:
public class Duck : DynamicAnimal
{
public string Quack()
{
return "QUACK!";
}
}
public class Cow : DynamicAnimal
{
public string Moo()
{
return "Mooooo!";
}
}
class Program
{
static void Main(string[] args)
{
var duck = new Duck();
var cow = new Cow();
Console.WriteLine("Can a duck quack?");
Console.WriteLine(DoQuack(duck));
Console.WriteLine("Can a cow quack?");
Console.WriteLine(DoQuack(cow));
Console.ReadKey();
}
public static string DoQuack(dynamic animal)
{
string result = animal.Quack();
return result ?? "... silence ...";
}
}
And your output would be:
Can a duck quack?
QUACK!
Can a cow quack?
... silence ...
Edit: I should note that this is the tip of the iceberg if you are able to use this approach and build on DynamicObject. You could write methods like bool HasMember(string memberName) if you so desired.
Try this:
using System.Linq;
using System.Reflection;
//...
public dynamic Quack(dynamic duck, int i)
{
Object obj = duck as Object;
if (duck != null)
{
//check if object has method Quack()
MethodInfo method = obj.GetType().GetMethods().
FirstOrDefault(x => x.Name == "Quack");
//if yes
if (method != null)
{
//invoke and return value
return method.Invoke((object)duck, null);
}
}
return null;
}
Or this (uses only dynamic):
public static dynamic Quack(dynamic duck)
{
try
{
//invoke and return value
return duck.Quack();
}
//thrown if method call failed
catch (RuntimeBinderException)
{
return null;
}
}
Implementation of the HasProperty method for every IDynamicMetaObjectProvider WITHOUT throwing RuntimeBinderException.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using Microsoft.CSharp.RuntimeBinder;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace DynamicCheckPropertyExistence
{
class Program
{
static void Main(string[] args)
{
dynamic testDynamicObject = new ExpandoObject();
testDynamicObject.Name = "Testovaci vlastnost";
Console.WriteLine(HasProperty(testDynamicObject, "Name"));
Console.WriteLine(HasProperty(testDynamicObject, "Id"));
Console.ReadLine();
}
private static bool HasProperty(IDynamicMetaObjectProvider dynamicProvider, string name)
{
var defaultBinder = Binder.GetMember(CSharpBinderFlags.None, name, typeof(Program),
new[]
{
CSharpArgumentInfo.Create(
CSharpArgumentInfoFlags.None, null)
}) as GetMemberBinder;
var callSite = CallSite<Func<CallSite, object, object>>.Create(new NoThrowGetBinderMember(name, false, defaultBinder));
var result = callSite.Target(callSite, dynamicProvider);
if (Object.ReferenceEquals(result, NoThrowExpressionVisitor.DUMMY_RESULT))
{
return false;
}
return true;
}
}
class NoThrowGetBinderMember : GetMemberBinder
{
private GetMemberBinder m_innerBinder;
public NoThrowGetBinderMember(string name, bool ignoreCase, GetMemberBinder innerBinder) : base(name, ignoreCase)
{
m_innerBinder = innerBinder;
}
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
var retMetaObject = m_innerBinder.Bind(target, new DynamicMetaObject[] {});
var noThrowVisitor = new NoThrowExpressionVisitor();
var resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
var finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
return finalMetaObject;
}
}
class NoThrowExpressionVisitor : ExpressionVisitor
{
public static readonly object DUMMY_RESULT = new DummyBindingResult();
public NoThrowExpressionVisitor()
{
}
protected override Expression VisitConditional(ConditionalExpression node)
{
if (node.IfFalse.NodeType != ExpressionType.Throw)
{
return base.VisitConditional(node);
}
Expression<Func<Object>> dummyFalseResult = () => DUMMY_RESULT;
var invokeDummyFalseResult = Expression.Invoke(dummyFalseResult, null);
return Expression.Condition(node.Test, node.IfTrue, invokeDummyFalseResult);
}
private class DummyBindingResult {}
}
}
impromptu-interface seems to be a nice Interface mapper for dynamic objects... It's a bit more work than I was hoping for, but seems to be the cleanest implementation of the examples presented... Keeping Simon's answer as correct, since it is still the closest to what I wanted, but the Impromptu interface methods are really nice.
The shortest path would be to invoke it, and handle the exception if the method does not exist. I come from Python where such method is common in duck-typing, but I don't know if it is widely used in C#4...
I haven't tested myself since I don't have VC 2010 on my machine
dynamic Quack(dynamic duck)
{
try
{
return duck.Quack();
}
catch (RuntimeBinderException)
{ return null; }
}
Have not see a correct answer here, MS provides an example now with casting to a dictionary
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
foreach (var property in (IDictionary<String, Object>)employee)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
// This code example produces the following output:
// Name: John Smith
// Age: 33