Lucene.NET TokenStream.Next method disappeared - c#

I have to update a project using Lucene.NET. It first time I meet this library, and I should update the references to a new version. So I did with Lucene references via a NuGet.
But actually I should in a way update some methods that disappeared in the new versions.
public abstract class AnalyzerView
{
public abstract string Name { get; }
public virtual string GetView(TokenStream tokenStream,out int numberOfTokens)
{
StringBuilder sb = new StringBuilder();
Token token = tokenStream.Next();
numberOfTokens = 0;
while (token != null)
{
numberOfTokens++;
sb.Append(GetTokenView(token));
token = tokenStream.Next();
}
return sb.ToString();
}
protected abstract string GetTokenView(Token token);
}
The documentation is not very clear for me. As I understood I should use something like
while (tokenStream.IncrementToken()) { ... }
but how to obtain that following token is a mystery for me.
I saw similar question on StackOverflow, but my problem is that I need to obtain a Token rather thatn a string, because I have some code that uses tokens, like this one:
public class TermWithOffsetsView : AnalyzerView {
public override string Name {
get { return "Terms With Offsets"; }
}
protected override string GetTokenView(Token token) {
return token.TermText() +
" Start: " + token.StartOffset().ToString().PadLeft(5) +
" End: " + token.EndOffset().ToString().PadLeft(5) +
"\r\n";
}
}

Finally, after some researches, implemented something like this:
public abstract class AnalyzerView
{
public abstract string Name { get; }
public virtual string GetView(TokenStream tokenStream,out int numberOfTokens)
{
StringBuilder sb = new StringBuilder();
numberOfTokens = 0;
while (tokenStream.IncrementToken())
{
numberOfTokens++;
sb.Append(GetTokenView(tokenStream));
}
return sb.ToString();
}
protected abstract string GetTokenView(TokenStream tokenStream);
}
with the derived class like this:
public class TermWithOffsetsView : AnalyzerView {
public override string Name {
get { return "Terms With Offsets"; }
}
protected override string GetTokenView(TokenStream tokenStream) {
ITermAttribute termAtt = tokenStream.AddAttribute<ITermAttribute>();
IOffsetAttribute offsetAtt=tokenStream.AddAttribute<IOffsetAttribute>();
return string.Format("{0} Start: {1} End: {2}{3}",
termAtt.Term,
offsetAtt.StartOffset.ToString().PadLeft(5),
offsetAtt.EndOffset.ToString().PadLeft(5),
Environment.NewLine);
}
}

Related

Json file was not found in Android

I am developing a game for mobile and can't create a normal save system because when playing on the phone the error is logged: Could not find the file.
I use the persistent data path as it was recommended in many answers and this method works well in Editor and Windows but not in Android.
Is there something I can do about it? Additional info: I am using IL2CPP as backend. Heard that it might create problem with serialization.
Full code:
using System;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class JsonFileWriter : MonoBehaviour
{
public string path;
public JsonData data;
string jsonDataString;
void Awake(){
path = Path.Combine(Application.persistentDataPath, "savegames", "data.json");
FileInfo file = new FileInfo(path);
if(!Directory.Exists(path)){
file.Directory.Create();
}
CheckFileExistance(path);
DeserializeData();
SerializeData();
}
public void SerializeData()
{
CheckFileExistance(path);
jsonDataString = JsonUtility.ToJson(data, true);
File.WriteAllText(path, jsonDataString);
Debug.Log("JSon data "+ jsonDataString);
}
public void DeserializeData()
{
string loadedJsonDataString = File.ReadAllText(path);
data = JsonUtility.FromJson<JsonData>(loadedJsonDataString);
Debug.Log("health: " + data.healthBoostAmt.ToString() + "secondChar: " + data.secondCharacterUnlocked.ToString());
}
public void WriteData(int hp,int money,int score,int damage, bool secondChar,int moneyAmt,int charSelected){
data = new JsonData(hp,money,score,damage,secondChar,moneyAmt,charSelected);
SerializeData();
}
#region Getters and seters
public int GetHealthBoosterAmt(){
DeserializeData();
return data.healthBoostAmt;
}
public int GetMoneyBoosterAmt(){
DeserializeData();
return data.moneyBoostAmt;
}
public int GetScoreBoostAmt(){
DeserializeData();
return data.scoreBoostAmt;
}
public int GetDamageBoostAmt(){
DeserializeData();
return data.damageBoostAmt;
}
public bool GetSecondCharBought(){
DeserializeData();
return data.secondCharacterUnlocked;
}
public int GetMoneyAmt(){
DeserializeData();
return data.moneyAmt;
}
public int GetSelectedCharID(){
DeserializeData();
return data.charSelected;
}
public string GetJsonDataString(){
return jsonDataString;
}
public void SetJsonDataString(string newValue){
//int hp,int money,int score,int damage, bool secondChar
data = JsonUtility.FromJson<JsonData>(newValue);
WriteData(data.healthBoostAmt,data.moneyBoostAmt,data.scoreBoostAmt,data.damageBoostAmt,data.secondCharacterUnlocked,data.moneyAmt,data.charSelected);
}
#endregion
void CheckFileExistance(string filePath){
if (!File.Exists(filePath)){
File.Create(filePath).Close();
}
}
}
[Serializable]
public class JsonData
{
public int healthBoostAmt;
public int moneyBoostAmt;
public int scoreBoostAmt;
public int damageBoostAmt;
public bool secondCharacterUnlocked;
public int moneyAmt;
public int charSelected;
public JsonData (int healthBoostAmt,int moneyBoostAmt,int scoreBoostAmt,int damageBoostAmt,bool secondCharacterUnlocked,int moneyAmt,int charSelected)
{
this.healthBoostAmt = healthBoostAmt;
this.moneyBoostAmt = moneyBoostAmt;
this.scoreBoostAmt = scoreBoostAmt;
this.damageBoostAmt = damageBoostAmt;
this.secondCharacterUnlocked = secondCharacterUnlocked;
this.moneyAmt = moneyAmt;
this.charSelected = charSelected;
}
public JsonData (){}
}

Is there a built in way of using snake case as the naming policy for JSON in ASP.NET Core 3?

I managed to get it working using the following code:
.AddNewtonsoftJson(options => {
options.SerializerSettings.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
});
However this makes MVC use Newtonsoft rather than System.Text.JSON which is faster, async and built in.
Looking at the naming policy options in System.Text.JSON I could only find CamelCase. Is there any native support for snake case? What is a better way of achieving snake case JSON naming style?
Just slight modification in pfx code to remove the dependency on Newtonsoft Json.Net.
String extension method to convert the given string to SnakeCase.
public static class StringUtils
{
public static string ToSnakeCase(this string str)
{
return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())).ToLower();
}
}
Then in our SnakeCaseNamingPolicy we can do
public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
public static SnakeCaseNamingPolicy Instance { get; } = new SnakeCaseNamingPolicy();
public override string ConvertName(string name)
{
// Conversion to other naming convention goes here. Like SnakeCase, KebabCase etc.
return name.ToSnakeCase();
}
}
The last step is to register our naming policy in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(
options => {
options.JsonSerializerOptions.PropertyNamingPolicy =
SnakeCaseNamingPolicy.Instance;
});
}
Using the model:
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureCelcius { get; set; }
public int TemperatureFahrenheit { get; set; }
public string Summary { get; set; }
}
Json output:
{
"date": "2019-10-28T08:26:14.878444+05:00",
"temperature_celcius": 4,
"temperature_fahrenheit": 0,
"summary": "Scorching"
}
At the moment there's no builtin support for snake case,
but .NET Core 3.0 allows to set up a custom naming policy by inheriting from JsonNamingPolicy.
You need to implement the ConvertName method with the snake case conversion.
(Newtonsoft Json.NET has an internal StringUtils class which shows how to handle this.)
The POC implementation below, re-uses Json.NET's SnakeCaseNamingStrategy only for the snake case conversion (, whereas the whole application uses System.Text.Json).
It is better to avoid having a dependency on Newtonsoft Json.Net for only the snake case conversion, but in this rather LAZY example below I don't want to rethink/reinvent a snake case conversion method.
The main point of this answer is how to hook a custom policy (and not the snake case conversion itself.) (There are many libraries and code samples that show how to do so.)
public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
private readonly SnakeCaseNamingStrategy _newtonsoftSnakeCaseNamingStrategy
= new SnakeCaseNamingStrategy();
public static SnakeCaseNamingPolicy Instance { get; } = new SnakeCaseNamingPolicy();
public override string ConvertName(string name)
{
/* A conversion to snake case implementation goes here. */
return _newtonsoftSnakeCaseNamingStrategy.GetPropertyName(name, false);
}
}
In Startup.cs you apply this custom SnakeCaseNamingPolicy.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(
options => {
options.JsonSerializerOptions.PropertyNamingPolicy =
SnakeCaseNamingPolicy.Instance;
});
}
An instance of the class below
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureCelcius { get; set; }
public int TemperatureFahrenheit { get; set; }
[JsonPropertyName("Description")]
public string Summary { get; set; }
}
will have a Json representation as:
{ "date" : "2019-10-28T01:00:56.6498885+01:00",
"temperature_celcius" : 48,
"temperature_fahrenheit" : 118,
"Description" : "Cool"
}
Note that the property Summary has been given the name Description,
which matches its System.Text.Json.Serialization.JsonPropertyNameAttribute.
I share a full implementation of #pfx 's solution here. The custom naming policy (copied from NewtonSoft):
using System.Text;
using System.Text.Json;
namespace Utils
{
public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name) => JsonUtils.ToSnakeCase(name);
}
public class JsonUtils
{
private enum SeparatedCaseState
{
Start,
Lower,
Upper,
NewWord
}
public static string ToSnakeCase(string s) => ToSeparatedCase(s, '_');
private static string ToSeparatedCase(string s, char separator)
{
if (string.IsNullOrEmpty(s))
{
return s;
}
StringBuilder sb = new StringBuilder();
SeparatedCaseState state = SeparatedCaseState.Start;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == ' ')
{
if (state != SeparatedCaseState.Start)
{
state = SeparatedCaseState.NewWord;
}
}
else if (char.IsUpper(s[i]))
{
switch (state)
{
case SeparatedCaseState.Upper:
bool hasNext = (i + 1 < s.Length);
if (i > 0 && hasNext)
{
char nextChar = s[i + 1];
if (!char.IsUpper(nextChar) && nextChar != separator)
{
sb.Append(separator);
}
}
break;
case SeparatedCaseState.Lower:
case SeparatedCaseState.NewWord:
sb.Append(separator);
break;
}
char c;
c = char.ToLowerInvariant(s[i]);
sb.Append(c);
state = SeparatedCaseState.Upper;
}
else if (s[i] == separator)
{
sb.Append(separator);
state = SeparatedCaseState.Start;
}
else
{
if (state == SeparatedCaseState.NewWord)
{
sb.Append(separator);
}
sb.Append(s[i]);
state = SeparatedCaseState.Lower;
}
}
return sb.ToString();
}
}
}
The following model is used in the simple example:
public class TestSerializer
{
public DateTime TimeStamp { get; set; }
public int CPUPower { get; set; }
}
And the example usage:
var data = new TestSerializer();
data.TimeStamp = DateTime.Now;
data.CPUPower = 10;
var serializeOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = new SnakeCaseNamingPolicy()
};
var json_string = JsonSerializer.Serialize(data, serializeOptions);
Console.WriteLine(json_string);
gives {"time_stamp":"2020-08-06T00:30:35.3815583-04:00","cpu_power":10}
There is a GitHub Repository with SnakeCase and KebabCase support for System.Text.Json, also a nuget package is available.
nuget
PM> Install-Package JorgeSerrano.Json.JsonSnakeCaseNamingPolicy
SnakeCase NamingPolicy
var person = new Person { FirstName = "Jorge", Birthday = DateTime.UtcNow, MyJobCity = "Madrid" };
var options = new JsonSerializerOptions { PropertyNamingPolicy = new JsonSnakeCaseNamingPolicy() };
var json = JsonSerializer.Serialize(person, options);
KebabCase NamingPolicy
var person = new Person { FirstName = "Jorge", Birthday = DateTime.UtcNow, MyJobCity = "Madrid" };
var options = new JsonSerializerOptions { PropertyNamingPolicy = new JsonKebabCaseNamingPolicy() };
var json = JsonSerializer.Serialize(person, options);
It is a bit late, but this solution will also solve cases like ABCItem or MyCPU.
This is just the concept, you can refine it to make it more versatile
using System.Collections.Generic;
namespace Extensions
{
public static class StringExtension
{
public static string ToSnakeCase(this string str)
{
// collect the final result
var snakeCase = new List<char>();
// check and add chars (using for loop for performance)
for (int i = 0; i < str.Length; i++)
{
if (i > 0 && char.IsUpper(str[i]) && !char.IsUpper(str[i + 1]))
{
snakeCase.Add('_');
}
snakeCase.Add(str[i]);
}
// build the new string
return new string(snakeCase.ToArray()).ToLower();
}
}
}
var snakeCase = "CPUMeter".ToSnakeCase();
var snakeCase = "PascalCase".ToSnakeCase();
var snakeCase = "camelCase".ToSnakeCase();
There's no need for a seperate kebab- and snake- case naming policy.
Also, if you absolutely want to minimize the number of unnecceesary character-conversions and lookups, the conversion method can be somewhat optimized
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
public class SeperatorNamingPolicy : JsonNamingPolicy
{
public SeperatorNamingPolicy(char seperator = '_')
{
Seperator = seperator;
}
public char Seperator { get; }
public override string ConvertName(string name)
{
IEnumerable<char> ToSeperated()
{
var e = name.GetEnumerator();
if (!e.MoveNext()) yield break;
yield return char.ToLower(e.Current);
while (e.MoveNext())
{
if (char.IsUpper(e.Current))
{
yield return Seperator;
yield return char.ToLower(e.Current);
}
else
{
yield return e.Current;
}
}
}
return new string(ToSeperated().ToArray());
}
}
However, if you just want a snake case naming policy without adding additional dependencies to your code, a dedicated snakecasenamingpolicy suffices:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
static IEnumerable<char> ToSnakeCase(CharEnumerator e)
{
if (!e.MoveNext()) yield break;
yield return char.ToLower(e.Current);
while (e.MoveNext())
{
if (char.IsUpper(e.Current))
{
yield return '_';
yield return char.ToLower(e.Current);
}
else
{
yield return e.Current;
}
}
}
return new string(ToSnakeCase(name.GetEnumerator()).ToArray());
}
}
You can of course use this by adding the json options in your startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// . . .
services
.AddControllers()
.AddJsonOptions(o => o.JsonSerializerOptions.PropertyNamingPolicy = new SnakeCaseNamingPolicy());
// . . .
}

C# Writing to XML file does not save object

I have some experience in Java. Today I started programming in C# because I like Visual Studio.
As an exercise i'm building a system that manages all employees in a company.
Im working on a class called Function:
public class Function
{
private String functionname;
private String department;
private double hourpay;
public String getFunc()
{
return functionname;
}
public String getDepartement()
{
return department;
}
public double getPay()
{
return hourpay;
}
public String toString()
{
return ("Function: " + functionname + "\n" + "Department: " + department + "\n" + "Hourly Pay: " + hourpay);
}
public void setFunctionName(string functionname)
{
this.functionname = functionname;
}
public void setDepartment(String department)
{
this.department = department;
}
public void setPay(double pay)
{
this.hourpay = pay;
}
A very simple basic class to model a function, Now I would like to save functions in a XML file.
What I have in mind is:
After I created a function I put it in a list called Functions (List functions)
I write the list to an XML file.
If I want to update the XML file I simply load the List, add a new function, and then overwrite it to the XML file.
I made my class functions like this;
public class Functions{
public List<Function> functions = new List<Function>();
public void addFunction(Function func){
functions.Add(func);
}
public void writeFunctions()
{
System.Xml.Serialization.XmlSerializer writer =
new System.Xml.Serialization.XmlSerializer(typeof(Functions));
System.IO.StreamWriter file = new System.IO.StreamWriter(
#"C:\CDatabase\Functions.xml");
writer.Serialize(file, this);
file.Close();
}
}
To test it I implemented this in a click event of a button:
Function programmer = new Function();
schoonmaker.setFunctionName("Programmer");
schoonmaker.setDepartment("IT");
schoonmaker.setPay(16.50);
FunctionDatabase.addFunction(schoonmaker);
FunctionDatabase.writeFunctions();
It creates the XML file(If its not there), and this is in the XML file:
<Functions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<functions>
<Function />
</functions>
</Functions>
Its empty, and I dont understand why and how to fix it.
I think i'm thinking too easy, but I cant find a fix.
Thanks in advance,
Chris
C# doesn't use getter and setter methods like Java. Create your properties like this:
private string functionname;
public string functionname
{
get { return functionname; }
set { functionname = value; }
}
A suggestion would be to use properties instead of getter/setter functions - they are a feature of C# which are used a lot.
For example, instead of:
public double getPay()
{
return hourpay;
}
Try:
public double HourPay { get; set; }
Or if you want to be able to perform actions within the getter/setter:
private double hourPay;
public double HourPay
{
get
{
return hourPay;
}
set
{
hourPay = value;
}
}
By using public properties in this way, the XML serializer should generate the file you were expecting.

Extract method in C# to use throughout project

Forgive the lengthy code here, and I also realise this may be a very basic fundamental question for any object-oriented developer, but I'm a front-end developer in at the deep end with .NET and trying to learn about classes and methods with an actual example. I've read resources to explain this stuff but immediately get stuck with the complexities of real-world code.
Basically I have a bunch of methods for adding comments to a web page and manipulating the status (marking as spam, deleting etc). Many of these methods call an 'EmailNotification' method, which sends an email to an administrator at each stage. It works great.
However, I'd like to use the 'EmailNotification' method elsewhere in the project, calling it from a different .cs file. When I try to do this it doesn't recognise the method because (I think!?) it's not a public static method.
Can anyone explain to me how to extract the EmailNotification method so that I can use it in different places around the code? I have tried creating a new class with this method inside it, but I just can't get it to work.
using System;
using System.Net.Mail;
namespace UComment.Domain
{
public class Comment
{
public delegate void CommentCreatedEventHandler(Comment sender, EventArgs e);
public delegate void CommentDeletedEventHandler(Comment sender, EventArgs e);
public delegate void CommentSpamEventHandler(Comment sender, EventArgs e);
public delegate void CommentApprovedEventHandler(Comment sender, EventArgs e);
public static event CommentCreatedEventHandler CommentCreated;
public static event CommentDeletedEventHandler CommentDeleted;
public static event CommentSpamEventHandler CommentSpam;
public static event CommentApprovedEventHandler CommentApproved;
protected virtual void OnCommentCreated(EventArgs e)
{
if (CommentCreated != null) CommentCreated(this, e);
}
protected virtual void OnCommentSpam(EventArgs e)
{
if (CommentSpam != null) CommentSpam(this, e);
}
protected virtual void OnCommentApproved(EventArgs e)
{
if (CommentApproved != null) CommentApproved(this, e);
}
protected virtual void OnCommentDelete(EventArgs e)
{
if (CommentDeleted != null) CommentDeleted(this, e);
}
public int Id { get; set; }
public int ParentNodeId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public bool Spam { get; set; }
public bool Approved { get; set; }
public DateTime Created { get; set; }
public string CommenText { get; set; }
public int StatusId { get; set; }
public Comment(int id)
{
Id = id;
var sqlHelper = DataLayerHelper.CreateSqlHelper(cms.GlobalSettings.DbDSN);
var reader = sqlHelper.ExecuteReader("select * from Comment where id = #id",
sqlHelper.CreateParameter("#id", id));
if(!reader.HasRecords) throw new Exception(string.Format("Comment with id {0} was not found", id));
reader.Read();
Name = reader.GetString("name");
ParentNodeId = reader.GetInt("nodeid");
Email = reader.GetString("email");
Website = reader.GetString("website");
Approved = reader.GetBoolean("approved");
Spam = reader.GetBoolean("Spam");
Created = reader.GetDateTime("created");
CommenText = reader.GetString("comment");
StatusId = reader.GetInt("statusid");
}
private Comment()
{
}
/// <summary>
/// Set as approved, mark as Not Spam - ignore HAM status
/// </summary>
public void MarkAsApproved()
{
var sqlHelper = DataLayerHelper.CreateSqlHelper(cms.GlobalSettings.DbDSN);
sqlHelper.ExecuteNonQuery(
"update comment set approved = 1, spam = 0, statusid = 2 where id = #id",
sqlHelper.CreateParameter("#id", Id));
OnCommentApproved(EventArgs.Empty);
// Send approval email
EmailNotification(1);
}
/// <summary>
/// Remove approval status. Ignore Spam and Ham states
/// </summary>
public void MarkAsNotApproved()
{
var sqlHelper = DataLayerHelper.CreateSqlHelper(cms.GlobalSettings.DbDSN);
sqlHelper.ExecuteNonQuery(
"update comment set approved = 0, statusid = 3 where id = #id",
sqlHelper.CreateParameter("#id", Id));
OnCommentApproved(EventArgs.Empty);
// Send rejection email
EmailNotification(2);
}
/// <summary>
/// Spam cannot be ham or approved
/// </summary>
public void MarkAsSpam()
{
var sqlHelper = DataLayerHelper.CreateSqlHelper(cms.GlobalSettings.DbDSN);
sqlHelper.ExecuteNonQuery(
"update comment set spam = 1, ham = 0, approved = 0, statusid = 3 where id = #id",
sqlHelper.CreateParameter("#id", Id));
OnCommentSpam(EventArgs.Empty);
// No email notification required - spammer not worthy of a reason for rejection
}
/// <summary>
/// Ham is "not spam" - approved comments from Akismet.
/// </summary>
public void MarkAsHam()
{
var sqlHelper = DataLayerHelper.CreateSqlHelper(cms.GlobalSettings.DbDSN);
sqlHelper.ExecuteNonQuery(
"update comment set spam = 0, ham = 1 where id = #id",
sqlHelper.CreateParameter("#id", Id));
// No email notification required, simply marking spam as ham
}
public void Delete()
{
if (Id < 1) return;
var sqlHelper = DataLayerHelper.CreateSqlHelper(cms.GlobalSettings.DbDSN);
sqlHelper.ExecuteNonQuery("delete from comment where id = #id", sqlHelper.CreateParameter("#id", Id));
Id = -1;
OnCommentDelete(EventArgs.Empty);
// Permanent deletion
}
public void Reject()
{
if (Id < 1) return;
var sqlHelper = DataLayerHelper.CreateSqlHelper(cms.GlobalSettings.DbDSN);
sqlHelper.ExecuteNonQuery("update comment set statusid = 3 where id = #id", sqlHelper.CreateParameter("#id", Id));
//Id = -1;
//OnCommentDelete(EventArgs.Empty);
// Send rejection email
EmailNotification(2);
}
public static Comment MakeNew(int parentNodeId, string name, string email, string website, bool approved, bool spam, DateTime created, string commentText, int statusId)
{
var c = new Comment
{
ParentNodeId = parentNodeId,
Name = name,
Email = email,
Website = website,
Approved = approved,
Spam = spam,
Created = created,
CommenText = commentText,
StatusId = statusId
};
var sqlHelper = DataLayerHelper.CreateSqlHelper(cms.GlobalSettings.DbDSN);
c.Id = sqlHelper.ExecuteScalar<int>(
#"insert into Comment(mainid,nodeid,name,email,website,comment,approved,spam,created,statusid)
values(#mainid,#nodeid,#name,#email,#website,#comment,#approved,#spam,#created,#statusid)",
sqlHelper.CreateParameter("#mainid", -1),
sqlHelper.CreateParameter("#nodeid", c.ParentNodeId),
sqlHelper.CreateParameter("#name", c.Name),
sqlHelper.CreateParameter("#email", c.Email),
sqlHelper.CreateParameter("#website", c.Website),
sqlHelper.CreateParameter("#comment", c.CommenText),
sqlHelper.CreateParameter("#approved", c.Approved),
sqlHelper.CreateParameter("#spam", c.Spam),
sqlHelper.CreateParameter("#created", c.Created),
sqlHelper.CreateParameter("#statusid", c.StatusId));
c.OnCommentCreated(EventArgs.Empty);
if (c.Spam)
{
c.OnCommentSpam(EventArgs.Empty);
}
if (c.Approved)
{
c.OnCommentApproved(EventArgs.Empty);
}
return c;
}
public override string ToString()
{
return #"ParentNodeId " + ParentNodeId + #"
Name " + Name + #"
Email " + Email + #"
Website " + Website + #"
Approved " + Approved + #"
Spam " + Spam + #"
Created "+ Created + #"
CommenText " + CommenText + Environment.NewLine;
}
/// <summary>
/// Send email notification
/// </summary>
public void EmailNotification(int notificationType)
{
var uCommentAdminEmail = Config.GetUCommentSetting("uCommentAdminEmail");
MailAddress to = null;
MailAddress from = new MailAddress(uCommentAdminEmail);
string subject = null;
string body = null;
switch (notificationType)
{
case 1:
// Comment approved
to = new MailAddress("me#mydomain.com");
subject = "Comment approved";
body = #"The comment you posted has been approved";
break;
case 2:
// Comment rejected
to = new MailAddress("me#mydomain.com");
subject = "Comment rejected";
body = #"The comment you posted has been rejected";
break;
}
MailMessage message = new MailMessage(from, to);
message.Subject = subject;
message.Body = body;
SmtpClient client = new SmtpClient();
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in EmailNotification: {0}", ex.ToString());
}
finally
{
//
}
}
}
}
Thanks for any pointers folks!
You can:
Extract it to a static method on static class
Create a singleton class that has an instance method
Create a class and interface for MessageSender and use DI to inject it where it's needed.
It depends on the size of the project: for small ones 1. may be enough, for big and complex (and if you have DI in place) 3 would be required.
What you have here is a public method, but because it's not declared as static (public static void EmailNotification...), it cannot be used without creating an instance of the class that it lives in.
using System;
namespace UComment.Domain
{
public class MyOtherClass
{
public void MyMethod()
{
Comment c = new Comment();
c.EmailNotification(1);
}
}
}
You could declare the method static which would let you call it like this:
using System;
namespace UComment.Domain
{
public class MyOtherClass
{
public void MyMethod()
{
Comment.EmailNotification(1);
}
}
}
If you're trying to use it from a different namespace then you would need to include the namespace either by a using statement or by specifying the full namespace inline.
using System;
using UComment.Domain;
namespace UComment.OtherNamespace
{
public class MyOtherClass
{
public void MyMethod()
{
Comment c = new Comment();
c.EmailNotification(1);
}
}
}
Or
using System;
namespace UComment.OtherNamespace
{
public class MyOtherClass
{
public void MyMethod()
{
UComment.Domain.Comment c = new UComment.Domain.Comment();
c.EmailNotification(1);
}
}
}
You are correct in thinking that if you wish to make this a common method, it should independent of the Comment class. The same limitations that I've just described apply to doing that. In addition, you'll have to make sure that any appropriate using statements are on the new class and that the dependencies within the EmailNotification are accounted for as well.
Your class makes too many things!
Split it in different types, each one has to solve only one type of problem according to Separation of concerns.
Same thing for the email sending, create an EmailSender class (or another name) and centralize the Send method there.
You can also create an interface (e.g. ISmtpClientFactory) to pass to the EmailSender class to abstract the concrete system to send emails and improve the testing experience.
Only on the production environment you really send emails, in the test environment you can use a fake factory to simulate the sending.
public class EmailSender
{
private readonly ISmtpClientFactory factory;
public EmailSender(ISmtpClientFactory factory)
{
this.factory = factory;
}
public void Send(MailMessage message)
{
using (var client = factory.Create())
{
using (message)
{
client.Send(message);
}
}
}
}
new EmailSender(new SmtpClientFactory()).Send(AdviceMessageFactory.Create(...));
You could put it in it's own class (like you already tried) and make the method static.
If this new class was EmailHelper, you would call the method like so:
EmailHelper.EmailNotification(1);
Depending on the namespace of the new class, you may also need a using statement at the top of every file you use it in.
It doesn't look like It should cause any issue If you create a (public) class and have that method in it. That method should accept all the properties it needs to send an email. You can create an instance of that class and call that method.

itunes listening to

within windows live messenger, it is possible to share the song you are currently listening to. what would i need to do to get this working within c# like libarys etc cannot find the correct documentation on google.
You'll need to use the iTunes SDK to interact with iTunes from .NET. So there's your Google search term. :)
Here's a start:
http://blogs.msdn.com/b/noahc/archive/2006/07/06/automating-itunes-with-c-in-net.aspx
http://blogs.msdn.com/b/dancre/archive/2004/05/08/128645.aspx
Here is a script for LinqPad in C# which does as requested. (see LinqPad.com)
Bonus! Artwork view.
It looks like this:
<Query Kind="Program">
<Namespace>iTunesLib</Namespace>
<Namespace>System.Security.Cryptography</Namespace>
</Query>
void Main()
{
var track = new iTunesApp().CurrentTrack;
if (track == null)
"nothing playing".Dump();
else
new Viewer(track,true).Dump();
}
public class Viewer
{
const string PREFIX = "itlps-";
private IITFileOrCDTrack store;
private bool materialize;
public string album { get { return store.Album; } }
public string band { get { return store.Artist; } }
public string song { get { return store.Name; } }
public string desc { get { return store.Description; } }
public int? artCnt { get {
if (store.Artwork == null) return null;
else return store.Artwork.Count; }
}
public IEnumerable<ImageViewer> art { get {
if (materialize)
{
foreach(var artT in store.Artwork)
{
var art = artT as IITArtwork;
string ext = ".tmp";
switch(art.Format)
{
case ITArtworkFormat.ITArtworkFormatBMP:
ext = ".BMP";
break;
case ITArtworkFormat.ITArtworkFormatJPEG:
ext = ".JPG";
break;
case ITArtworkFormat.ITArtworkFormatPNG:
ext = ".PNG";
break;
}
string path = Path.Combine(Path.GetTempPath(),PREFIX+Path.GetRandomFileName()+ext);
art.SaveArtworkToFile(path);
yield return new ImageViewer(path);
}
}
yield break; }
}
public Viewer(IITFileOrCDTrack t,bool materializeArt = false)
{
store = t;
materialize = materializeArt;
}
public Viewer(IITTrack t,bool materializeArt = false)
{
store = t as IITFileOrCDTrack;
materialize = materializeArt;
}
}
public class ImageViewer
{
public string hash { get { return _hash.Value; } }
static private string _path { get; set; }
public object image { get { return _image.Value; } }
static private SHA1Managed sha = new SHA1Managed();
private Lazy<object> _image = new Lazy<object>(() => {return Util.Image(_path);});
private Lazy<string> _hash = new Lazy<string>(() =>
{
string hash = string.Empty;
using (FileStream stream = File.OpenRead(_path))
{
byte [] checksum = sha.ComputeHash(stream);
hash = BitConverter.ToString(checksum).Replace("-", string.Empty);
}
return hash;
});
public ImageViewer(string path)
{
_path = path;
}
}
last i checked this functionality is included out of the box all you need is to have itunes and windows live messenger installed and activate "what im listening to" and it shows this in your messenger status. if you are looking to create a bot that messages this out to a contact that is a different story tho that you will need to write a script for

Categories