I have the following code which I'm trying to use to save and load data from a settings XML file on my phone (the caller is accessed via an interface in a PCL)
// caller
public void SetStringValue(string name, string val)
{
UserData.SetPropertyValue(this, name, val);
}
// userdata file
namespace PreferencesXML.iOS
{
public static class UserData
{
public static object GetPropertyValue(object data, string propertyName)
{
return data.GetType().GetProperties().SingleOrDefault(pi => pi.Name == propertyName).GetValue(data, null);
}
public static void SetPropertyValue<T>(object data, string propertyName, T value)
{
data.GetType().GetProperties().SingleOrDefault(pi => pi.Name == propertyName).SetValue(data, value);
}
private static string pUserSettingsFile;
private static UserSetting userSetting;
public static UserSetting UserSetting
{
get
{
if (userSetting == null)
{
if (File.Exists(UserSettingsFile))
{
userSetting = Serialiser.XmlDeserializeObject<UserSetting>(UserSettingsFile);
}
else
{
userSetting = new UserSetting();
Serialiser.XmlSerializeObject(userSetting, UserSettingsFile);
}
}
return userSetting;
}
set
{
if (value == null)
{
throw new ArgumentNullException("value is null!");
}
// end if
userSetting = value;
if (File.Exists(UserSettingsFile))
{
File.Delete(UserSettingsFile);
}
Serialiser.XmlSerializeObject(userSetting, UserSettingsFile);
}
}
public static string UserSettingsFile
{
get
{
if (string.IsNullOrEmpty(pUserSettingsFile))
{
pUserSettingsFile = Path.Combine(AppDelegate.Self.ContentDirectory, "UserSettings.xml");
}
return pUserSettingsFile;
}
}
public static string Company
{
get
{
return UserSetting.companyName;
}
set
{
UserSetting settings = UserSetting;
settings.companyName = value;
UserSetting = settings;
}
}
public static double Pi
{
get
{
return UserSetting.pi;
}
set
{
UserSetting settings = UserSetting;
settings.pi = value;
UserSetting = settings;
}
}
public static bool OnOff
{
get
{
return UserSetting.onOff;
}
set
{
UserSetting settings = UserSetting;
settings.onOff = value;
UserSetting = settings;
}
}
}
public class UserSetting
{
public string companyName{ get; set; }
public double pi{ get; set; }
public bool onOff{ get; set; }
}
}
As you can see, it's not doing anything mind boggling difficult. The reader part of this works fine, but the SetPropertyValue constantly returns a fail at the SingleOrDefault.
This is down to the caller extension method extending the class the caller is in rather than the UserData class.
As the UserData class is static, I can't create an object instance of it and pass that in in place of the this parameter, neither can I pass UserData in directly or as a generic parameter (such as this.SetPropertyValue<UserData>(...)). I've attempted to make the class non-static, which gets me a bit further, but not much.
Is there a way that I can use this code to store data to and from my UserData class?
Related
Is there a standard naming convention for the properties/methods of a node/relationship class when working with Neo4jClient?
I'm following this link Neo4jClient - Retrieving relationship from Cypher query to create my relationship class
However, there are certain properties of my relationship which i can't get any value despite the relationship having it. While debugging my code, i realized certain properties was not retrieved from the relationship when creating the relationship object.
this is my relationship class
public class Creates
{
private string _raw;
private int _sourcePort;
private string _image;
private int _DestinationPort;
private int _eventcode;
private string _name;
private string _src_ip;
private int _src_port;
private string _dvc;
private int _signature_ID;
private string _dest_ip;
private string _computer;
private string _sourceType;
private int _recordID;
private int _processID;
private DateTime _time;
private int _dest_port;
public string Raw { get { return _raw; } set { _raw = value; } }
public int SourcePort { get { return _sourcePort; } set { _sourcePort = value; } }
public string Image { get { return _image; } set { _image = value; } }
public int DestinationPort { get { return _DestinationPort; } set { _DestinationPort = value; } }
public int Eventcode { get { return _eventcode; } set { _eventcode = value; } }
public string Name { get { return _name; } set { _name = value; } }
public string Src_ip { get { return _src_ip; } set { _src_ip = value; } }
public int Src_port { get { return _src_port; } set { _src_port = value; } }
public string DVC { get { return _dvc; } set { _dvc = value; } }
public int Signature_ID { get { return _signature_ID; } set { _signature_ID = value; } }
public string Dest_ip { get { return _dest_ip; } set { _dest_ip = value; } }
public string Computer { get { return _computer; } set { _computer = value; } }
public string SourceType { get { return _sourceType; } set { _sourceType = value; } }
public int RecordID { get { return _recordID; } set { _recordID = value; } }
public int ProcessID { get { return _processID; } set { _processID = value; } }
public DateTime Indextime { get { return _time; } set { _time = value; } }
public int Dest_port { get { return _dest_port; } set { _dest_port = value; } }
}
This is another class
public class ProcessConnectedIP
{
public Neo4jClient.RelationshipInstance<Pivot> bindto { get; set; }
public Neo4jClient.Node<LogEvent> bindip { get; set; }
public Neo4jClient.RelationshipInstance<Pivot> connectto { get; set; }
public Neo4jClient.Node<LogEvent> connectip { get; set; }
}
This is my neo4jclient query to get the relationship object
public IEnumerable<ProcessConnectedIP> GetConnectedIPs(string nodeName)
{
try
{
var result =
this.client.Cypher.Match("(sourceNode:Process{name:{nameParam}})-[b:Bind_IP]->(bind:IP_Address)-[c:Connect_IP]->(connect:IP_Address)")
.WithParam("nameParam", nodeName)
.Where("b.dest_ip = c.dest_ip")
.AndWhere("c.Image=~{imageParam}")
.WithParam("imageParam", $".*" + nodeName + ".*")
.Return((b, bind, c, connect) => new ProcessConnectedIP
{
bindto = b.As<RelationshipInstance<Creates>>(),
bindip = bind.As<Node<LogEvent>>(),
connectto = c.As<RelationshipInstance<Creates>>(),
connectip = connect.As<Node<LogEvent>>()
})
.Results;
return result;
}catch(Exception ex)
{
Console.WriteLine("GetConnectedIPs: Error Msg: " + ex.Message);
return null;
}
}
This is the method to read the results
public void MyMethod(string name)
{
IEnumerable<ProcessConnectedIP> result = clientDAL.GetConnectedIPs(name);
if(result != null)
{
var results = result.ToList();
Console.WriteLine(results.Count());
foreach (ProcessConnectedIP item in results)
{
Console.WriteLine(item.Data.Src_ip);
Console.WriteLine(item.bindto.StartNodeReference.Id);
Console.WriteLine(item.bindto.EndNodeReference.Id);
Console.WriteLine(item.connectto.StartNodeReference.Id);
Console.WriteLine(item.connectto.EndNodeReference.Id);
Node<LogEvent> ans = item.bindip;
LogEvent log = ans.Data;
Console.WriteLine(log.Name);
Node<LogEvent> ans1 = item.connectip;
LogEvent log1 = ans1.Data;
Console.WriteLine(log1.Name);
}
}
}
Somehow, i'm only able to populate the relationship object with src_ip/src_port/dest_ip/dest_port values. the rest are empty.
Is there any possible reason why? I've played with upper/lower cases on the properties names but it does not seem to work.
This is the section of the graph im working with
This is the relationship properties sample:
_raw: Some XML dataSourcePort: 49767Image: C:\Windows\explorer.exeDestinationPort: 443EventCode: 3Name: Bind
IPsrc_ip: 172.10.10.104dvc: COMPUTER-NAMEsrc_port:
49767signature_id: 3dest_ip: 172.10.10.11Computer:
COMPUTRE-NAME_sourcetype:
XmlWinEventLog:Microsoft-Windows-Sysmon/OperationalRecordID:
13405621ProcessId: 7184_time: 2017-08-28T15:15:39+08:00dest_port: 443
I'm not entirely sure how your Creates class is ever populated, in particular those fields - as your Src_port property doesn't match the src_port in the sample you provided (case wise).
I think it's probably best to go back to a super simple version. Neo4jClient will map your properties to the properties in the Relationship as long as they have the same name (and it is case-sensitive).
So start with a new Creates class (and use auto properties - it'll make your life a lot easier!)
public class Creates
{
public string Computer { get; set; }
}
Run your query with that and see if you get a result, then keep on adding properties that match the name and type you expect to get back (int, string etc)
It seems that i have to give neo4j node/relationship property names in lowercase and without special characters at the start of the property name, in order for the above codes to work.
The graph was not created by me at the start thus i had to work on it with what was given. I had to get the developer who created the graph to create the nodes with lowercases in order for the above to work.
I have an extension method for System.Object to serialize and deserialize objects using Json.Net. this is my Extension methods:
public static void SaveToFile(this object data, string FileName)
{
using (StreamWriter writer = new StreamWriter(FileName))
{
string encode = WpfApplication.Helper.Encrypt(JsonConvert.SerializeObject(data));
writer.Write(encode);
writer.Close();
}
}
public static void LoadFromFile<t>(this object data, string FileName)
{
using (StreamReader reader = new StreamReader(FileName))
{
data = JsonConvert.DeserializeObject<t>(WpfApplication.Helper.Decrypt(reader.ReadToEnd()));
reader.Close();
}
}
and It's the class that I want to deserialize:
public class CardPack
{
#region Properties
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private List<FlashCard> cards;
public List<FlashCard> Cards
{
get { return cards; }
set { cards = value; }
}
private bool registered;
public bool Registered
{
get { return registered; }
set { registered = value; }
}
private int currentCardIndex;
public int CurrentCardIndex
{
get { return currentCardIndex; }
set { currentCardIndex = value; }
}
public string RegisterKey { get; set; }
public string ViewName { get; set; }
public List<FlashCard> TodayCards { get; set; }
#endregion
~CardPack()
{
foreach (FlashCard card in cards)
{
card.Check();
}
currentCardIndex = 0;
TodayCards = null;
this.SaveToFile(string.Format(System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Split(#"file:\\")[1] + #"\Packs\{0}.json", name));
}
but whenever I deserialize the class cards is empty and I don't know how to resolve the problem. Can anybody help me?
Update
I find the error when I had this code:
public CardPack(string Name)
{
this.name = Name;
this.LoadFromFile<CardPack>(string.Format(System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Split(#"file:\\")[1] + #"\Packs\{0}.json", name));
foreach (var item in cards)
{
if (item.NextTime == null)
{
int a = 0;
}
}
TodayCards = cards.Where(c => c.NextTime.Date == DateTime.Today).ToList();
}
because the application closed when it tries to run foreach (var item in cards)!
I asked here and found out that cards is empty!
update2 I serialized the CardPack object with a little different structure. in previous structure Cards property was read-only.
I found that data = JsonConvert.DeserializeObject<t>(WpfApplication.Helper.Decrypt(reader.ReadToEnd())); in extension method doesn't change to 'data' class then Cards in CardPack is always null. I'll ask a question to find out why I cant set the class from it's extension method later.
I have a class, with a public property "appController", as follows:
public class FAST
{
#region Props
public AppController.AppControllerClass appController = new AppController.AppControllerClass();
#endregion
#region Contructors
public FAST(AppController.AppControllerClass appcontroller)
{
this.appController = appcontroller;
}
#endregion
}
I have another few class, in which I would like to use the appController of FAST, the above class.They look like:
public class Forecast
{
#region Properties
private int _forecastnumber;
public int ForecastNumber
{
get { return _forecastnumber; }
set { _forecastnumber = value; }
}
private DateTime _startdate;
public DateTime StartDate
{
get { return _startdate; }
set { _startdate = value; }
}
private DateTime _enddate;
public DateTime EndDate
{
get { return _enddate; }
set { _enddate = value; }
}
private DateTime _deadline;
public DateTime Deadline
{
get { return _deadline; }
set { _deadline = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private string _type;
public string Type
{
get { return _type; }
set { _type = value; }
}
private string _description;
public string Description
{
get { return _description; }
set { _description = value; }
}
private string _status;
public string Status
{
get { return _status; }
set { _status = value; }
}
#endregion
#region Constructors
public Forecast()
{
}
#endregion
#region Methods
public static void InsertForecast(Forecast forecast)
{
try
{
this.appController.Execute(appController.nDC.FASTData.InsertForecast(forecast.StartDate, forecast.EndDate, forecast.Deadline, forecast.Type, forecast.Name, forecast.Description, forecast.Status));
}
catch (Exception ex)
{
this.appController.LogError(ex);
}
}
#endregion
}
I want to be able to declare the FAST class once, passing in the AppController, then use my other classes freely, and they will use the appcontroller of the FAST class.
Can this be done at all? (inheritance?)
Thanks for any help.
It sounds like you simply want a static class for your FAST class. If you define the AppController variable as static, it will be accessible from anywhere.
I would say no to inheritance. Inheritance suggests an "is" relationship, e.g. "Forecast is a specialized version of the app controller." Aggregation, a specialized form of object composition, suggests a "has" relationship, e.g. "Forecast has an app controller."
http://en.wikipedia.org/wiki/Object_composition#Aggregation
You could add a setter method to set your FAST object as a property of Forecast:
public FAST appController { get; set; }
And then
var f = new FAST(new AppController.AppControllerClass());
var forecast = new Forecast();
var forecast2 = new Forecast();
forecast.appController = f;
forecast2.appController = f;
I have a problem with deserialization in my silverlight project. I have class Obj with this methods and variables.
public class Obj
{
private string _name;
private Uri _iconUri;
private string _stringUri;
private List<ObjItem> _items = new List<ObjItem>();
public List<ObjItem> Items
{
get { return _items; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public Uri IconUri
{
get
{
return _iconUri;
}
}
public string StringUri { get { return _stringUri; } }
public int Count
{
get { return _items.Count; }
}
public Obj(string name,string uriString = null)
{
_name = name;
if (uriString == null)
{
_iconUri = null;
}
else
{
_iconUri = new Uri(uriString, UriKind.Relative);
}
_stringUri = uriString;
}
// for deserialization
public Obj()
{
}
}
Before serialization all fields are not empty!
After deserialization all fields are not empry except _iconUri and _stringUri fields.
Why is it happened?
I'll be waiting for your replies.
Thank you!
Those two don't have setters. Silverlight has a restricted security model, where you cant can't cheat by accessing private fields; only public members can be accessed. So: add public setters to those properties if you want them to work with most serializers on SL.
To be specific: _name is being set by the Name setter, and _items is being set in the constructor via the field-initializer.
when for Perperty created a private field,Do it is compulsor??
and when do not created?
enter code here
namespace ApplicationStartSample
{
public class Configuration
{
private Configuration()
{
}
private static Configuration _Current;
public static Configuration Current
{
get
{
if (_Current == null)
_Current = new Configuration();
return _Current;
}
}
private const string Path = "Software\\MFT\\Registry Sample";
public bool EnableWelcomeMessage
{
get
{
return bool.Parse(Read("EnableWelcomeMessage", "false"));
}
set
{
Write("EnableWelcomeMessage", value.ToString());
}
}
public string Company //why do not create private field?
{
get
{
return Read("Company", "MFT");
}
set
{
Write("Company", value);
}
}
public string WelcomeMessage
{
get
{
return Read("WelcomeMessage", string.Empty);
}
set
{
Write("WelcomeMessage", value);
}
}
public string Server
{
get
{
return Read("Server", ".\\Sqldeveloper");
}
set
{
Write("Server", value);
}
}
public string Database
{
get
{
return Read("Database", "Shop2");
}
set
{
Write("Database", value);
}
}
private static string Read(string name, string #default)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(Path, false);
if (key == null)
return #default;
try
{
string result = key.GetValue(name).ToString();
key.Close();
return result;
}
catch
{
return #default;
}
}
private static void Write(string name, string value)
{
try
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(Path, true);
if (key == null)
key = Registry.CurrentUser.CreateSubKey(Path);
key.SetValue(name, value);
key.Close();
}
catch
{
}
}
}
}
If you're asking if you can eliminate the private field for your Current property, you could do this (though it would no longer initialise Configuration lazily):
public class Configuration
{
static Configuration()
{
Current = new Configuration();
}
public static Configuration Current { get; private set; }
}
Note: This is an Auto-Implemented Property and requires C# 3.0.
You could also use a public field instead (though if you ever need to change this to a property, you would need to recompile anything that's calling it):
public class Configuration
{
public static Configuration Current = new Configuration();
}