I have found some threads about this problem, like this and this but I cannot figure out how I could implement this for my code.
I have something like this:
public sealed class Party
{
public Party()
{
load();
}
....
public async void Load()
{
string fileName = this.Name + ".xml";
var files = ApplicationData.Current.LocalFolder.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByName).GetResults();
var file = files.FirstOrDefault(f => f.Name == fileName);
if (file != null)
{
using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(fileName))
{
XmlSerializer serializer = new XmlSerializer(typeof(Party));
Party data = (Party)serializer.Deserialize(stream);
this = data;
}
}
}
}
This throws me the "cannot assign to ' this ' because it is read-only". Since I read a file and I need to await it, it have to be async, and then I cannot have the class as a return type.
Any ideas for how to deserialize this to itself?
You can't assign to this. It's an instance of an object, and it makes no sense to change it.
Either have a static method that returns the Party (and use that to create the class):
public static Party Load()
{
// ... Deserialize
return (Party)serializer.Deserialize(stream);
}
Or load the information into your class using the deserialized object (which would be inefficient, since they're the same type):
public void Load()
{
// ... Deserialize
Party data = (Party)serializer.Deserialize(stream);
this.Name = data.Name;
this.PartyInfo = data.PartyInfo;
}
Clearly, the static method should be preferred here, and is considered the factory pattern.
Related
Problem: I have many file types that I want to parse. Each one parses a file and returns a result (List<>) of objects. I want to have just one IFileParser interface and specify the parser type and return set at time of calling Parse
I have an interface like this
public interface IFileParser
{
TResponse Parse<TFileParserType,TResponse>(string file);
}
being injected into a service like this
private readonly IFileParser _fileParser;
public CarService(IFileParser fileParser)
{
_fileParser = fileParser;
}
being used
var cardatas = _fileParser.Parse<CarFileParser, List<CarData>>("car.txt");
var bikedatas = _fileParser.Parse<BikeFileParser, List<BikeData>>("bike.txt");
implementation - this part does not work...why?
error returned is
Cannot implicitly convert type 'System.Collections.Generic.List<CarData>' to 'System.Collections.Generic.List<TResponse>'
public class CarFileParser : IFileParser
{
public List<CarData> Parse(string filePath)
{
return new List<CarData>() //does not work...why??
}
public TResponse Parse<TType, TResponse>(string file)
{
throw new NotImplementedException();
//this is what it should be
//but how do I return a List<CarData>
}
}
Not claiming this to be the Answer. Does this help:
public interface IFileParser<TResponse>
{
TResponse Parse(string file);
}
public class CarFileParser : IFileParser<List<CarData>>
{
public List<CarData> Parse(string file)
{
throw new NotImplementedException();
}
}
first of all, return type should match with return value:
public List<CarData> Parse(string filePath)
{
return new List<CarData>() //Will work..
}
while doing the type conversion, a list cannot be convert to class. If you want this, create a property in class.
var cardatas = _fileParser.Parse<CarFileParserList, List<CarData>>("car.txt");
class CarFileParser
{
public List<CarFile> CarFileParserList{get;set;}
}
public class CarFile
{
//create property here
}
then you can use this code:
var cardatas = _fileParser.Parse<List<CarFile>, List<CarData>>("car.txt");
var carFileParser= new CarFileParser();
carFileParser.CarFileParserList=cardatas;
If it always returns a list, maybe try
List<TResponse> Parse<TFileParserType, TResponse>(string file);
and then
List<CarData> cardatas = _fileParser.Parse<CarFileParser, CarData>("car.txt");
(or possibly ICollection / IEnumerable)
In general, I would prefer to implement the type / interface like this. Not sure if this works with your injection.
// Put the type of data on the interface / type
public interface IFileParser<TData>
{
IEnumerable<TData> Parse(string file);
}
// Implement the interface
public class CarParser : IFileParser<CarData>
{
...
}
// The method where to inject the implementation:
public IEnumerable<TData> Parse<TData>(IFileParser<TData> parser, string file)
{
return parser.Parse(file);
}
// The implementations would have to be injected here:
private readonly IFileParser<CarData> _carFileParser;
private readonly IFileParser<BikeData> _bikeFileParser;
var carData = Parse(_carFileParser, file);
var bikeData = Parse(_bikeFileParser, file);
My unit testing method is as follows
[Test]
public void TrackPublicationChangesOnCDSTest()
{
//Arrange
// objDiskDeliveryBO = new DiskDeliveryBO();
//Act
var actualResult = objDiskDeliveryBO.TrackPublicationChangesOnCDS();
//Assert
var expectedZipName = 0;
Assert.AreEqual(expectedZipName, actualResult);
}
The Actual method TrackPublicationChangesOnCDS in BO is as follows
public int TrackPublicationChangesOnCDS()
{
var resultFlag = -1;
try
{
string pubUpdateFileCDSPath = CommonCalls.PubUpdateFileCDSPath;
string pubUpdateFileLocalPath = CommonCalls.PubUpdateFileLocalPath;
if (File.Exists(pubUpdateFileCDSPath))
File.Copy(pubUpdateFileCDSPath, pubUpdateFileLocalPath, true);
if (File.Exists(pubUpdateFileLocalPath))
{
string[] pubRecords = File.ReadAllLines(pubUpdateFileLocalPath);
var pubRecordsExceptToday = pubRecords.Where(p => !p.Trim().EndsWith(DateTime.Now.ToString("dd/MM/yy"))).ToList();
resultFlag = new DiskDeliveryDAO().TrackPublicationChangesOnCDS(pubRecordsExceptToday);
File.WriteAllText(pubUpdateFileLocalPath, string.Empty);
string[] pubRecordsCDS = File.ReadAllLines(pubUpdateFileCDSPath);
var pubRecordsTodayCDS = pubRecordsCDS.Where(p => p.Trim().EndsWith(DateTime.Now.ToString("dd/MM/yy"))).ToList();
File.WriteAllLines(pubUpdateFileCDSPath, pubRecordsTodayCDS);
}
return resultFlag;
}
catch (Exception)
{
return -1;
}
}
While debugging Debugger comes till
string pubUpdateFileCDSPath = CommonCalls.PubUpdateFileCDSPath;
But CommonCalls.PubUpdateFileCDSPath; return empty string . It should return a file path . when the method is called directly it works fine . It doesn't work when it is called inside a unit testing method.
CommonCalls.PubUpdateFileCDSPath is a static property defined as below .
public static string PubUpdateFileCDSPath
{
get { return GetXmlConfigValue("PubUpdateFileCDSPath"); }
}
public static string GetXmlConfigValue(string nodeName)
{
var xml = new XmlDocument();
xml.Load(ConfigValuesXml);
var node = xml.SelectSingleNode("JanesOfflineDeliveryService/" + nodeName);
return node != null ? node.InnerText : string.Empty;
}
Configvaluesxml is a xml file path . Contents of the file is
<JanesOfflineDeliveryService>
<PubUpdateFileCDSPath>D:\OfflineDelivery\CDS\pub_update.txt</PubUpdateFileCDSPath>
<PubUpdateFileLocalPath>D:\pub_update.txt</PubUpdateFileLocalPath>
</JanesOfflineDeliveryService>
In your test scenario GetXmlConfigValue("PubUpdateFileCDSPath") does not exist, so string empty is returned. Thats why you should avoid static methods, because they are not mockable. A workaround could be to pass the path variables into the method.
Using static dependencies make unit testing code in isolation difficult. invert the dependency by abstracting and injecting them into the dependent class.
public interface ICommonCalls {
string PubUpdateFileCDSPath { get; }
string PubUpdateFileLocalPath { get; }
}
the implementation of the above interface would either wrap the your static calls or better yet just implement them.
The dependent class would be refactored to allow for the dependency inversion.
public class DiskDeliveryBO {
private readonly ICommonCalls CommonCalls;
public DiskDeliveryBO(ICommonCalls common) {
this.CommonCalls = common;
}
//...other code removed for brevity.
}
However the target method also has a lot of tight coupling to implementation concerns like the file system. That too should be abstracted and inverted out of the dependent class.
I have a static class wherein I am reading an XML to build a dictionary.
Now this initialization is done in the static constructor.
In order to test this Initialize method, I have to somehow stub out the reading of XML logic and just give it an XDocument for testing, but not sure how can I do that.
internal static class MasterMnemonicsLookup
{
private static Dictionary<string, StateCoverageMnemonic[]> masterMnemonics = new Dictionary<string, StateCoverageMnemonic[]>();
private static StateCoverageMnemonic[] stateCoverageMnemonics;
static MasterMnemonicsLookup()
{
Initialize();
}
private static void Initialize()
{
var resource = XDocument.Parse(GetResourceTextFile("MasterMnemonics.xml"));
var serializer = new XmlSerializer(typeof (MasterMnemonicsType));
var model = (MasterMnemonicsType) serializer.Deserialize(resource.CreateReader());
var stateCoverageMnemonicsList = new List<StateCoverageMnemonic>();
foreach (var masterMnemonic in model.MasterMnemonics)
{
var stateCoverageMnemonicsXml = new List<StateCoverageMnemonic>();
var excludedStates = RiskStates.None;
StateCoverageMnemonic allStateCoverageMnemonic = null;
foreach (var stateCoverageMnemonic in masterMnemonic.StateCoverageMnemonics)
{
var state = stateCoverageMnemonic.StateCode;
if (!state.HasFlag(RiskStates.All))
{
excludedStates = excludedStates | state;
var mnemonic = stateCoverageMnemonic.Mnemonic;
var coverageCode = stateCoverageMnemonic.CoverageCode;
var stateCoverageMnemonicTemp = new StateCoverageMnemonic(state, mnemonic, coverageCode);
stateCoverageMnemonicsXml.Add(stateCoverageMnemonicTemp);
}
else
{
//// TODO: If All occurs twice should we throw an exception
allStateCoverageMnemonic = new StateCoverageMnemonic(state, stateCoverageMnemonic.Mnemonic, stateCoverageMnemonic.CoverageCode);
}
}
if (allStateCoverageMnemonic != null)
{
stateCoverageMnemonicsXml.Add(new StateCoverageMnemonic(RiskStates.All ^ excludedStates, allStateCoverageMnemonic.Mnemonic, allStateCoverageMnemonic.CoverageCode));
}
stateCoverageMnemonicsList.AddRange(stateCoverageMnemonicsXml);
masterMnemonics.Add(masterMnemonic.MasterMnemonic, stateCoverageMnemonicsXml.ToArray());
}
stateCoverageMnemonics = stateCoverageMnemonicsList.ToArray();
}
private static string GetResourceTextFile(string filename)
{
string result = string.Empty;
using (Stream stream = typeof(MasterMnemonicsLookup).Assembly.GetManifestResourceStream("Geico.Applications.Business.CoverageApi.DomainLayer.DataLayer." + filename))
{
var streamReader = new StreamReader(stream);
result = streamReader.ReadToEnd();
}
return result;
}
}
Using static contructors in this way is not advised, and your scenario is a good example why. You might try the singleton pattern using a public instance constructor that accepts an XDocument. (You can use internal, but this makes it harder to unit test). This is a simple form of dependency injection.
For testing, an instance of your class can simply be created by your testing framework with the test XDocument.
For your live application, a static instance of your class can be initialized and held by a container type, and the appropriate XDocument can be passed in privately (within the container).
I agree with Darious Vaughan-Scott
But if you want to keep using the static constructor you may want to put the loading logic into a seperate class which makes it easier to test.
For example
internal class MasterMnemonicsLoader
{
public void Load(
XDocument resource,
Dictionary<string, StateCoverageMnemonic[]> masterMnemonics,
StateCoverageMnemonic[] stateCoverageMnemonics)
{
//Do the loading here
}
}
and in the Initialize method you can call the Load method
private static void Initialize()
{
var resource = XDocument.Parse(GetResourceTextFile("MasterMnemonics.xml"));
var loader = MasterMnemonicsLoader();
loader.Load(resource, masterMnemonics, stateCoverageMnemonics);
Im trying to find out if there is a way to create a local instance of my object that is being referenced from the app domain, reason for this is due to the high amount of chatter I get during all the execution of the method. So instead of having to call the remote object the whole time I'd like to just call a local instance created inside the method.
I've been looking at RemotingServices Marshal and GetObjectData methods but haven't been able to figure out if they will work or not and google hasn't helped either
so the class definition looks as follows
[XmlRoot("SI")]
public class SI : MarshalByRefObject, IXmlSerializable
And then runtime an instance of the class looks like this.
Name: Service
Value: {System.Runtime.Remoting.Proxies.__TransparentProxy}
Type: SI {System.Runtime.Remoting.Proxies.__TransparentProxy}
I was hoping to accomplish what I needed along the lines of the following
var uri =RemotingServices.GetObjectUri(Service);
var serv = RemotingServices.Marshal(Service, uri, typeof(SI)); //Service is the object I described above
SerializationInfo info = new SerializationInfo(typeof(SI), new FormatterConverter());
StreamingContext context = new StreamingContext(StreamingContextStates.All);
serv.GetObjectData(info, context);
var t2 = serv.GetRealObject(context);
I get the following error when calling GetRealObject
"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
I still haven't found any way to implement this, anyone perhaps have some suggestions?
Okay. So either install Unity or create your own resource locator (object dictionary).
The following is a resource locator I wrote:
using System;
using System.Collections.Generic;
namespace Bizmonger.Client.Infrastructure
{
public class ServiceLocator
{
#region Members
Dictionary<Type, object> _dictionary = new Dictionary<Type, object>();
static ServiceLocator _serviceLocator = null;
#endregion
public static ServiceLocator Instance
{
get
{
if (_serviceLocator == null)
{
_serviceLocator = new ServiceLocator();
}
return _serviceLocator;
}
}
public object this[Type key]
{
get
{
if (!_dictionary.ContainsKey(key))
{
_dictionary.Add(key, Activator.CreateInstance(key));
}
return _dictionary[key];
}
set
{
_dictionary[key] = value;
}
}
public bool ContainsKey(Type type)
{
return _dictionary.ContainsKey(type);
}
public void Load(object data)
{
if (data == null) { return; }
RemoveExisting(data);
_dictionary.Add(data.GetType(), data);
}
public void Load(Type type, object data)
{
if (data == null) { return; }
RemoveExisting(data);
_dictionary.Add(type, data);
}
#region Helpers
private void RemoveExisting(object data)
{
bool found = _dictionary.ContainsKey(data.GetType());
if (found)
{
_dictionary.Remove(data.GetType());
}
}
#endregion
}
}
Then you can do this in your client:
var uri =RemotingServices.GetObjectUri(Service);
var serv = RemotingServices.Marshal(Service, uri, typeof(SI));
ServiceLocator.Instance.Load(serv);
You can retrieve this object like this:
var server = ServiceLocator.Instance[typeof(some_class)] as some_class;
I'm trying out Generics and I had this (not so) great idea of creating an XMLSerializer class. The code I pieced together is below:
public class Persist<T>
{
private string _path;
public Persist(string path) {
this._path = path;
}
public void save(T objectToSave)
{
XmlSerializer s = new XmlSerializer(typeof(T));
TextWriter w = new StreamWriter(this._path);
try { s.Serialize(w, objectToSave); }
catch (InvalidDataException e) { throw e; }
w.Close(); w.Dispose();
}
public T load()
{
XmlSerializer s = new XmlSerializer(typeof(T));
TextReader r = new StreamReader(this._path);
T obj;
try { obj = (T)s.Deserialize(r); }
catch (InvalidDataException e) { throw e; }
r.Close(); r.Dispose();
return obj;
}
}
Here's the problem: It works fine on Persist<List<string>> or Persist<List<int>> but not on Persist<List<userObject>> or any other custom (but serializable) objects. userObject itself is just a class with two {get;set;} properties, which I have serialized before.
I'm not sure if the problems on my Persist class (generics), XML Serialization code, or somewhere else :( Help is very much appreciated~
Edit:
code for userObject
public class userObject
{
public userObject(string id, string name)
{
this.id = id;
this.name = name;
}
public string id { get;private set; }
public string name { get;set; }
}
Looks to me like your code should just work - even though it does have a few flaws.
EDIT: Your userObject class isn't serializable. Xml serialization only works on types with a public, parameterless constructor - the current class won't work. Also, you should really rewrite your code to avoid explicit calls to .Close() or .Dispose() and instead prefer using where possible - as is, you might get random file locking if at any point during serialization an error occurs and your method terminates by exception - and thus doesn't call .Dispose().
Personally, I tend to use a just-for-serialization object hierarchy that's just a container for data stored in xml and avoids any behavior - particularly side effects. Then you can use a handly little base class that makes this simple.
What I use in my projects is the following:
public class XmlSerializableBase<T> where T : XmlSerializableBase<T>
{
static XmlSerializer serializer = new XmlSerializer(typeof(T));
public static T Deserialize(XmlReader from) { return (T)serializer.Deserialize(from); }
public void SerializeTo(Stream s) { serializer.Serialize(s, this); }
public void SerializeTo(TextWriter w) { serializer.Serialize(w, this); }
public void SerializeTo(XmlWriter xw) { serializer.Serialize(xw, this); }
}
...which caches the serializer in a static object, and simplifies usage (no generic type-paramenters needed at call-locations.
Real-life classes using it:
public class ArtistTopTracks {
public string name;
public string mbid;//always empty
public long reach;
public string url;
}
[XmlRoot("mostknowntracks")]
public class ApiArtistTopTracks : XmlSerializableBase<ApiArtistTopTracks> {
[XmlAttribute]
public string artist;
[XmlElement("track")]
public ArtistTopTracks[] track;
}
Sample serialization calls:
using (var xmlReader = XmlReader.Create([...]))
return ApiArtistTopTracks.Deserialize(xmlReader);
//[...]
ApiArtistTopTracks toptracks = [...];
toptracks.SerializeTo(Console.Out);
There can be a number of reasons why your code fails: This text is particularly helpful when having issues: Troubleshooting Common Problems with the XmlSerializer . Maybe you have some type hierarchy in your user objects and the serializer does not know about it?