How to serialize in a XML a custom IEnumerable? - c#

I've created a class which derives from IEnumerable<T>. T is a OQTemplate, and this one implements IXmlSerializable correctly. But I don't know how to implement the following class.
public class OQTemplateCollection : IEnumerable<OQTemplate>, IEnumerable
{
private readonly List<OQTemplate> entries;
public OQTemplateCollection()
{
this.entries = new List<OQTemplate>();
}
public OQTemplateCollection(IEnumerable<OQTemplate> source)
{
this.entries = new List<OQTemplate>(source);
}
public void Add(OQTemplate qt)
{
entries.Add(qt);
}
public IEnumerator<OQTemplate> GetEnumerator()
{
return entries.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public OQTemplate this[int index]
{
get { return entries[index]; }
}
}
I'd like just to have a XML like this:
<OQTemplateCollection>
<OQTemplate ... />
<OQTemplate ... />
</OQTemplateCollection>

Related

xunit:Get test method name in ClassData's class

This is my sample test,
[Theory]
[BeforeAfterMethod]
[ClassData(typeof(GetTestData))]
public void Test3(int a)
{
ReporterLogs.Pass("value of a: " + a);
//TODO
}
And my GetTestData class is,
public class GetTestData : IEnumerable<object[]>
{
private string _currentTestMethodName;
private List<object[]> _data = new List<object[]>();
public GetTestData()
{
Console.WriteLine(**Print test method name here**);
_data.Add(new object[] { 10 } });
}
public IEnumerator<object[]> GetEnumerator()
{
return _data.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
I want to print the current test(i.e. Test3 in this case) method name inside GetTestData class. How it can be achieved. Thanks in advance.
It can be achieved by using DataAttribute in Xunit as follows,
public class GetTestData : DataAttribute
{
private List<object[]> _data = new List<object[]>();
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
if (testMethod == null)
throw new ArgumentNullException(testMethod.Name);
_data.Add(new object[] { 10 });
return _data;
}
}

Deserialize to custom list [duplicate]

This question already has answers here:
How to serialize/deserialize a custom collection with additional properties using Json.Net
(6 answers)
Closed 7 years ago.
I created a custom List class that maintains a set of item ids for performance reasons:
public class MyCustomList : List<ItemWithID>
{
private HashSet<int> itemIDs = new HashSet<int>();
public MyCustomList()
{
}
[JsonConstructor]
public MyCustomList(IEnumerable<ItemWithID> collection)
: base(collection)
{
itemIDs = new HashSet<int>(this.Select(i => i.ID));
}
public new void Add(ItemWithID item)
{
base.Add(item);
itemIDs.Add(item.ID);
}
public new bool Remove(ItemWithID item)
{
var removed = base.Remove(item);
if (removed)
{
itemIDs.Remove(item.ID);
}
return removed;
}
public bool ContainsID(int id)
{
return itemIDs.Contains(id);
}
}
I want to deserialize this List from a simply JSON array e.g.:
JsonConvert.DeserializeObject<MyCustomList>("[{ID:8},{ID:9}]");
this will cause JSON.NET to call only the empty constructor, so my itemIDs list remains empty. Also the Add method is not called.
How does JSON.NET add the items to the list so I can add logic at that place.
(this is about deserialization without properties that should be persistent in the json string, so the suggested duplicate question has nothing to do with this one)
Solution:
public class MyCustomList : IList<ItemWithID>
{
private HashSet<int> itemIDs = new HashSet<int>();
private List<ItemWithID> actualList = new List<ItemWithID>();
public void Add(ItemWithID item)
{
actualList.Add(item);
itemIDs.Add(item.ID);
}
public bool Remove(ItemWithID item)
{
var removed = actualList.Remove(item);
if (removed)
{
itemIDs.Remove(item.ID);
}
return removed;
}
public bool ContainsID(int id)
{
return itemIDs.Contains(id);
}
public int IndexOf(ItemWithID item)
{
return actualList.IndexOf(item);
}
public void Insert(int index, ItemWithID item)
{
actualList.Insert(index, item);
itemIDs.Add(item.ID);
}
public void RemoveAt(int index)
{
itemIDs.Remove(actualList[index].ID);
actualList.RemoveAt(index);
}
public ItemWithID this[int index]
{
get
{
return actualList[index];
}
set
{
actualList[index] = value;
if (!itemIDs.Contains(value.ID))
{
itemIDs.Add(value.ID);
}
}
}
public void Clear()
{
actualList.Clear();
itemIDs.Clear();
}
public bool Contains(ItemWithID item)
{
return actualList.Contains(item);
}
public void CopyTo(ItemWithID[] array, int arrayIndex)
{
actualList.CopyTo(array, arrayIndex);
}
public int Count
{
get { return actualList.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public IEnumerator<ItemWithID> GetEnumerator()
{
return actualList.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
You could deserialize to the form the constructor expects, then call that yourself.
var collection = JsonConvert.DeserializeObject<ItemID[]>("[{ID:8},{ID:9}]");
var aCustomList = new MyCustomList(collection);
Your problem isn't with JSON deserialization, your MyCustomList class needs to derive from IList if you want to be able to override the Add method. See THIS for details.

Override IEnumerable<T> Where

I've written a class that implements IEnumerable :
public class MyEnumerable : IEnumerable<MyClass>
{
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<MyClass> GetEnumerator()
{
//Enumerate
}
}
I'd like to "override" the Where method. What I want to do is :
MyEnumerable myEnumerable = new MyEnumerable();
MyEnumerable myEnumerable2 = myEnumerable.Where(/*some predicate*/);
This is not possible for the moment because myEnumerable.Where() returns an IEnumerable.
What I want is that myEnumerable.Where() returns a MyEnumerable.
Is that possible to do this ?
Thank you
Sure - just add a Where method to MyEnumerable. The Linq Where method is an extension method, so it's not technically an override. you're "hiding" the linq method.
public class MyEnumerable : IEnumerable<MyClass>
{
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<MyClass> GetEnumerator()
{
//Enumerate
}
public MyEnumerable Where()
{
// implement `Where`
}
}
There are some caveats, though:
Your Where method will only be called if the declared type is MyEnumerable - it will not be called on variables of type IEnumerable<MyClass> (or any collection that implements it, like List<MyClass>
There are several overloads of Where that will need to be implemented as well if you want to maintain consistently with Linq.
Update
From your comment your enumerator is a lazy file enumerator and you want to be able to select items from it based on a predicate and still have the laziness.
You could create another class inheriting that class or an interface to help with this.
Here is an example
public class FileItem
{
//Some properties
}
public interface IFileEnumerator : IEnumerable<FileItem>
{
IFileEnumerator Where(Func<FileItem, bool> predicate);
}
public class FileEnumerator : IFileEnumerator
{
private readonly string fileName;
public FileEnumerator(string fileName)
{
this.fileName = fileName;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<FileItem> GetEnumerator()
{
var items = new List<FileItem>();
//Read from file and add lines to items
return items.GetEnumerator();
}
public IFileEnumerator Where(Func<FileItem, bool> predicate)
{
return new MemoryEnumerator(ToEnumerable(GetEnumerator()).Where(predicate));
}
private static IEnumerable<T> ToEnumerable<T>(IEnumerator<T> enumerator)
{
while (enumerator.MoveNext())
{
yield return enumerator.Current;
}
}
}
public class MemoryEnumerator : IFileEnumerator
{
private readonly IEnumerable<FileItem> items;
public MemoryEnumerator(IEnumerable<FileItem> items)
{
this.items = items;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<FileItem> GetEnumerator()
{
return items.GetEnumerator();
}
public IFileEnumerator Where(Func<FileItem, bool> predicate)
{
return new MemoryEnumerator(items.Where(predicate));
}
}

Implementing two generic IEnumerable interfaces with different type parameter

Having code as below, getting a compile error - "... does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()'".
How to implement the non-generic version of GetEnumerator?
public class Giraffe { }
public class Pigeon { }
public class Sample : IEnumerable<Giraffe>, IEnumerable<Pigeon>
{
IEnumerator<Giraffe> IEnumerable<Giraffe>.GetEnumerator()
{
return null;
}
IEnumerator<Pigeon> IEnumerable<Pigeon>.GetEnumerator()
{
return null;
}
}
Try:
public class Pets :IEnumerable, IEnumerable<Giraffe>, IEnumerable<Pigeon>
{
IEnumerator<Giraffe> IEnumerable<Giraffe>.GetEnumerator()
{
return null;
}
IEnumerator<Pigeon> IEnumerable<Pigeon>.GetEnumerator()
{
return null;
}
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
if I understand your problem correctly, here is a sample how you can implement non-generic Enumerator in your class
public class Sample : IEnumerable<Giraffe>, IEnumerable<Pigeon>
{
IEnumerator<Giraffe> IEnumerable<Giraffe>.GetEnumerator()
{
return null;
}
IEnumerator<Pigeon> IEnumerable<Pigeon>.GetEnumerator()
{
return null;
}
IEnumerator IEnumerable.GetEnumerator()
{
return null; //your logic for the enumerator
}
}
since the generic IEnumerable<T> inherits non-generic IEnumerable so implementing IEnumerable.GetEnumerator would define an implementation for the same.
you may additionally declare the class as public class Sample : IEnumerable, IEnumerable<Giraffe>, IEnumerable<Pigeon> for more clarity
example
public class Sample : IEnumerable, IEnumerable<Giraffe>, IEnumerable<Pigeon>
{
IEnumerator<Giraffe> IEnumerable<Giraffe>.GetEnumerator()
{
return null;
}
IEnumerator<Pigeon> IEnumerable<Pigeon>.GetEnumerator()
{
return null;
}
IEnumerator IEnumerable.GetEnumerator()
{
return null; //your logic for the enumerator
}
}

Passing non generic objects into a generic collection

I have a set of rules which is defined by this interface:
public interface IRule<in T>
{
bool IsBroken(T dataObject);
}
Sample implementations:
class Rule1:IRule<DateTime>
{
public bool IsBroken(DateTime dataObject)
{
throw new NotImplementedException();
}
}
class Rule2:IRule<int>
{
public bool IsBroken(int dataObject)
{
throw new NotImplementedException();
}
}
I have another class which passess back the lsit of rules as below:
class RulesCollection
{
public IEnumerable<IRule<what>> GetAllRules()
{
yield return new Rule1();
yield return new Rule2();
}
}
The issue 'am facing here is- how will pass back the rule1 & rule2 into IEnumerable<IRule<T>>, since T is going to be different for various rules it does't allow me to do so. Is there a way to get over this issue?
Using .NET 4.
Depending on the meaning of the return value of IsBroken, you could do something like:
public class RuleWrapper<T> : IRule<object>
{
private readonly IRule<T> inner;
public RuleWrapper(IRule<T> inner)
{
this.inner = inner;
}
public bool IsBroken(object obj)
{
return obj is T && this.inner.IsBroken((T)obj);
}
}
and then:
public IEnumerable<IRule<object>> GetAllRules()
{
yield return new RuleWrapper<DateTime>(new Rule1());
yield return new RuleWrapper<int>(new Rule2());
}

Categories