I have the following two methods:
class Debug
{
static bool OutputToConsole = true;
public static void Log(string Type, string URL, StringBuilder Parameters)
{
string Output = Type + ":" + new string(' ', 9 - Type.Length) + URL + " { " + Parameters.ToString() + " }";
Trace.WriteLine(Output);
if(OutputToConsole) Console.WriteLine(Output);
}
public static void Log(string Data)
{
string Output = "Response: " + Data;
Trace.WriteLine(Output);
if(OutputToConsole) Console.WriteLine(Output);
}
}
If you'll notice, it's only the string Output that changes.
The 2 lines after it are the same in both methods.
I was just wondering if there is there a way to keep to the DRY principle and combine these 2 methods?
Refactor the common code to a private helper function: (Visual studio will do all of this for you by highlighting the relevant section of code, right clicking, and choosing Refactor -> extract method...)
private static void LogHelper(string text)
{
Trace.WriteLine(text);
if(OutputToConsole) Console.WriteLine(text);
}
(Note the name change to ensure it has a different signature from Log(string Data).)
Then just call that function from both of the others.
Not sure how much of an improvement this is...
class Debug
{
static bool OutputToConsole = true;
public static void LogRequest(string type, string url, StringBuilder params)
{
log(type + ":" + new string(' ', 9 - type.Length) + url + " { " + params.ToString() + " }");
}
public static void LogResponse(string data)
{
log("Response: " + data);
}
private static void log(string msg)
{
Trace.WriteLine(msg);
if(OutputToConsole) Console.WriteLine(msg);
}
}
There is likely no way to combine the two methods and get any real value out of it because the Output generated is different, but you could create a method that does the actual trace:
public static void Trace(string Output)
{
Trace.WriteLine(Output);
if(OutputToConsole) Console.WriteLine(Output);
}
and then call that from those methods.
You could use optional parameters if you wanted, it's a bit unusual, but interesting:
public static void Log(string Data = null, string Type = null, string URL = null, StringBuilder Parameters = null)
{
string Output = "";
if (Data != null)
{
Output = "Response: " + Data;
}
else if (Type != null && URL != null && Parameters != null)
{
Output = Type + ":" + new string(' ', 9 - Type.Length) + URL + " { " + Parameters.ToString() + " }";
}
else
{
throw new ArgumentException("Provide yada yada arguments lala");
}
Trace.WriteLine(Output);
if (OutputToConsole) Console.WriteLine(Output);
}
Use it like this:
Log(Data: "Test");
StringBuilder sb = new StringBuilder();
Log(Type: "myType", URL: "www.bla", Parameters: sb);
Related
Can anyone help me to resolve my healthKit capability issue for a unity app.
I am trying to add healthKit capability to my unity app. I am using BEHEALTHKIT and HealthKitBuildProcessor.cs editor class to add capability and other dependencies. Following are the code I am using .But for some reason healthkit Capability and entitlements are not adding through this code (permission parameters are adding to plist), and returning null when I print Debug.Log("newEntitlements: " + newEntitlements);Also my build failing with an error saying "provisioning profile doesn't support the HealthKit Capability"
I have already added HealthKit capability for the profile from developer.apple.com.
Unity version: 2019.4.4f1
public class HealthKitBuildProcessor : IProcessSceneWithReport
{
private static string shareString = null;
private static string updateString = null;
private static string clinicalString = null;
/*! #brief required by the IProcessScene interface. Set high to let other postprocess scripts run first. */
public int callbackOrder {
get { return 100; }
}
/*! #brief Searches for HealthKitDataTypes objects & reads the usage strings for the OnPostprocessBuild phase.
#param scene the scene being processed.
#param report a report containing information about the current build
*/
public void OnProcessScene(Scene scene, BuildReport report) {
GameObject[] rootObjects = scene.GetRootGameObjects();
foreach (GameObject obj in rootObjects) {
HealthKitDataTypes types = obj.GetComponentInChildren<HealthKitDataTypes>();
if (types != null) {
if (types.AskForSharePermission()) {
HealthKitBuildProcessor.shareString = types.healthShareUsageDescription;
}
if (types.AskForUpdatePermission()) {
HealthKitBuildProcessor.updateString = types.healthUpdateUsageDescription;
}
/*if (types.AskForClinicalPermission()) {
HealthKitBuildProcessor.clinicalString = types.clinicalUsageDescription;
}*/
}
}
}
/*! #brief Updates the Xcode project.
#param buildTarget the target build platform
#param path the path of the target build
*/
[PostProcessBuildAttribute(10)]
public static void OnPostprocessBuild(BuildTarget buildTarget, string path) {
Debug.Log("--- BEHEALTHKIT POST-PROCESS BUILD ---");
if (buildTarget == BuildTarget.iOS) {
//string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";
//Debug.Log("BE:PROJECT PATH :" + projPath);
var projPath = PBXProject.GetPBXProjectPath(path);
var proj = new PBXProject();
proj.ReadFromString(System.IO.File.ReadAllText(projPath));
#if UNITY_2019_3_OR_NEWER
string mainTarget = proj.GetUnityMainTargetGuid();
string frameworkTarget = proj.GetUnityFrameworkTargetGuid();
Debug.Log("--- BE: UNITY_2019_3_OR_NEWER ---");
Debug.LogFormat("main target: {0}", mainTarget);
Debug.LogFormat("framework target: {0}", frameworkTarget);
#else
string targetName = PBXProject.GetUnityTargetName();
string mainTarget = proj.TargetGuidByName(targetName);
Debug.Log("---BE: ELSE UNITY_2019_3_OR_NEWER ---");
Debug.Log("main target: {0}", mainTarget);
Debug.Log("targetName: ", targetName);
#endif
bool addHealthRecordsCapability = (clinicalString != null);
//Debug.Log("addHealthRecordsCapability: ", addHealthRecordsCapability);
// Info.plist
//-----------
Debug.Log("---BE: PLIST ---");
var info = ProcessInfoPList(path, addHealthRecordsCapability);
// Entitlements
//--------------
Debug.Log("---BE: ProcessEntitlements ---");
string entitlementsRelative = ProcessEntitlements(path, proj, mainTarget, info, addHealthRecordsCapability);
#if UNITY_2019_3_OR_NEWER
// add HealthKit capability
Debug.Log("------projPath "+projPath);
ProjectCapabilityManager capabilities = new ProjectCapabilityManager(projPath, "Entitlements.entitlements", null, mainTarget);
capabilities.AddHealthKit();
Debug.Log("---BE:Capability UNITY_2019_3_OR_NEWER ---");
// add HealthKit Framework
//proj.AddFrameworkToProject(frameworkTarget, "HealthKit.framework", true);
// Set a custom link flag
//proj.AddBuildProperty(frameworkTarget, "OTHER_LDFLAGS", "-ObjC");
#else
// add HealthKit capability
Debug.Log("---ELSE BE:Capability UNITY_2019_3_OR_NEWER ---");
Debug.Log("projectPath:" + projPath);
Debug.Log("entitlementsRelative:" + entitlementsRelative);
Debug.Log("targetName:" + targetName);
ProjectCapabilityManager capabilities = new ProjectCapabilityManager(projPath, entitlementsRelative, targetName);
capabilities.AddHealthKit();
// add HealthKit Framework
proj.AddFrameworkToProject(mainTarget, "HealthKit.framework", true);
// Set a custom link flag
proj.AddBuildProperty(mainTarget, "OTHER_LDFLAGS", "-ObjC");
#endif
proj.WriteToFile(projPath);
}
}
// -------------------------------
internal static PlistDocument ProcessInfoPList(string path, bool addHealthRecordsCapability) {
string plistPath = Path.Combine(path, "Info.plist");
PlistDocument info = GetInfoPlist(plistPath);
PlistElementDict rootDict = info.root;
// // Add the keys
if (HealthKitBuildProcessor.shareString != null) {
rootDict.SetString("NSHealthShareUsageDescription", HealthKitBuildProcessor.shareString);
}
else {
Debug.LogError("unable to read NSHealthShareUsageDescription");
}
if (HealthKitBuildProcessor.updateString != null) {
rootDict.SetString("NSHealthUpdateUsageDescription", HealthKitBuildProcessor.updateString);
}
if (addHealthRecordsCapability) {
rootDict.SetString("NSHealthClinicalHealthRecordsShareUsageDescription", HealthKitBuildProcessor.clinicalString);
}
// Write the file
info.WriteToFile(plistPath);
return info;
}
internal static string ProcessEntitlements(string path, PBXProject proj, string target, PlistDocument info, bool addHealthRecordsCapability) {
string entitlementsFile;
string entitlementsRelative;
string entitlementsPath;
Debug.Log("PATH: " + path);
Debug.Log("TARGET: " + target);
String test= proj.GetUnityMainTargetGuid();
Debug.Log("TEST proj: " + test);
entitlementsRelative = proj.GetBuildPropertyForConfig(target, "CODE_SIGN_ENTITLEMENTS");
Debug.Log("entitlementsRelative: " + entitlementsRelative);
Debug.LogFormat("get build property [{0}, {1} = {2}]", target, "CODE_SIGN_ENTITLEMENTS", entitlementsRelative);
PlistDocument entitlements = new PlistDocument();
if (entitlementsRelative == null) {
string projectname = GetProjectName(info);
Debug.Log("projectname: " + projectname);
entitlementsFile = Path.ChangeExtension("Entitlements", "entitlements");
Debug.Log("entitlementsFile: " + entitlementsFile);
entitlementsRelative = Path.Combine(path, entitlementsFile);
Debug.Log("entitlementsRelative: " + entitlementsRelative);
entitlementsPath = Path.Combine(path, entitlementsRelative);
Debug.Log("entitlementsPath: " + entitlementsPath);
//proj.AddFileToBuild(target, proj.AddFile(entitlementsRelative, entitlementsRelative, PBXSourceTree.Source));
Debug.LogFormat("add build property [{0}, {1}] => {2}", target, "CODE_SIGN_ENTITLEMENTS", entitlementsRelative);
proj.AddBuildProperty(target, "CODE_SIGN_ENTITLEMENTS", entitlementsFile);
string newEntitlements = proj.GetBuildPropertyForConfig(target, "CODE_SIGN_ENTITLEMENTS");
Debug.Log("newEntitlements: " + newEntitlements);
Debug.LogFormat("=> {0}", newEntitlements);
}
else {
entitlementsPath = Path.Combine(path, entitlementsRelative);
Debug.Log("ELSE:entitlementsPath " + entitlementsPath);
}
ReadEntitlements(entitlements, entitlementsPath);
entitlements.root.SetBoolean("com.apple.developer.healthkit", true);
if (addHealthRecordsCapability) {
Debug.Log("addHealthRecordsCapability =TRUE ");
var healthkitAccess = entitlements.root.CreateArray("com.apple.developer.healthkit.access");
healthkitAccess.AddString("health-records");
}
SaveEntitlements(entitlements, entitlementsPath);
return entitlementsRelative;
}
// -------------------------------
internal static void ReadEntitlements(PlistDocument entitlements, string destinationPath) {
Debug.Log("READING Entitlements [ReadEntitlements]");
Debug.Log("READING from destinationPath [ReadEntitlements]"+ destinationPath);
if (System.IO.File.Exists(destinationPath)) {
try {
Debug.LogFormat("reading existing entitlements: '{0}'.", destinationPath);
entitlements.ReadFromFile(destinationPath);
}
catch (Exception e) {
Debug.LogErrorFormat("error reading from file: {0}", e);
}
}
}
internal static void SaveEntitlements(PlistDocument entitlements, string destinationPath) {
try {
Debug.Log("----SaveEntitlements---");
entitlements.WriteToFile(destinationPath);
}
catch (Exception e) {
Debug.LogErrorFormat("error writing to file: {0}", e);
}
}
internal static PlistDocument GetInfoPlist(string plistPath) {
// Get the plist file
PlistDocument plist = new PlistDocument();
plist.ReadFromFile(plistPath);
return plist;
}
internal static string GetProjectName(PlistDocument plist) {
string projectname = plist.root["CFBundleDisplayName"].AsString();
return projectname;
}
}
I don't know about Unity, but from Xcode when you add a capability for health kit it will update the entitlement file by itself
I need to create an EXE file with my application, I can pass strings with manipulating the string format but I cannot pass the other variables that I need to ex:byte array, here is my code if this helps:
using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Windows;
namespace ACompiler.CompWorker
{
class CompilerWorker
{
public static byte[] testarray = SomeClass.SomeArray;
public static string Key = "Testkey12";
public static void Compile()
{
CSharpCodeProvider CompileProvider = new CSharpCodeProvider();
CompilerParameters CompileProviderParameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, AppDomain.CurrentDomain.BaseDirectory + "Compiled.exe", true);
CompileProviderParameters.GenerateExecutable = true;
string test= #"using System;
namespace Tests
{
class Program
{
static void Main(string[] args)
{
byte[] Content = " + testarray + #";
string Key = """ + Key + #""";
Console.WriteLine(""Key: "" + EKey);
Console.WriteLine(Content);
Console.ReadLine();
}
}
}
";
var Result = CompileProvider.CompileAssemblyFromSource(CompileProviderParameters, test);
}
}
}
Basically I want to move the "testarray" into the compiled app, I hope someone can point me to the right direction!
The trick is to "serialize" the data back in to code the compiler can compile. Try this:
var arrayCode = "new byte[] { " + string.Join(", ", testarray) + " }";
string test = #"using System;
namespace Tests
{
class Program
{
static void Main(string[] args)
{
byte[] Content = " + arrayCode + #";
string Key = """ + Key + #""";
Console.WriteLine(""Key: "" + EKey);
foreach(byte b in Content)
{
Console.WriteLine(b.ToString());
}
Console.ReadLine();
}
}
}
";
Keep in mind, you can't do Console.WriteLine on a byte array object and have it spit out each item. You will have to iterate over the items to print them out. I updated your code to do it the proper way.
I have this method I want to generate log text(txt) file and the file structure would follow query string data which are passed on to this method like in culturename, langid, themeid, saleschannel. I want the the file to be generated in the form of culturename_saleschannel_themeid_langid.txt if there are four parameters and saleschannel_themeid_langid.txt depends if there are three parameters coming or themeid_langid.txt if there are two parameters and accordingly. Please help me create a log text file in this format or how to do this separately.
private void Log(string message, bool debugOnly, bool waitOnThis, LogType logType, string culturename, int langid, int themeid, int saleschannel)
{
string logFormat = Environment.NewLine + "{0}\t {1}\t{2}" + Environment.NewLine;
//message = message + " - " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
message = string.Format(logFormat, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),logType.ToString().Substring(0,3).ToUpper(), message);
_logFileName = string.Format(_logFileNamePattren, _jobConfigurationData.Name, LogFileId, _logFileDate);
string filePath = _jobConfigurationData.LogFolderPath;
if (!string.IsNullOrEmpty(filePath))
filePath += "\\" + _logFileName;
if (debugOnly == false || (debugOnly && _jobConfigurationData.BuildMode == BuildMode.Debug))
{
if (!string.IsNullOrEmpty(filePath))
{
if(!Directory.Exists(Path.GetDirectoryName(filePath)))
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
File.AppendAllText(filePath, message, System.Text.Encoding.UTF8);
}
Console.Write(message);
}
Something like this
_logFileName = (string.IsNullOrEmpty(culturename)? string.Empty : (culturename + "_")) +
(saleschannel == 0 ? string.Empty : (saleschannel+"_")) +
themeid+ "_" + langid +".txt";
Or you are talking about function overloads?
I have this frustrating problem that I can't seem to solve.
I try to fill a TextBox with text from a public static string.
But when I run the program it just shows a blank text box with nothing in it.
I don't have any errors so it's hard for me to understand what I'm doing wrong.
Here is the code I have:
public ShowMp3()
{
InitializeComponent();
OverzichttxtBox.Text = OverzichtMP3();
}
public static String OverzichtMP3()
{
String overzicht = "";
foreach (Mp3Player player in Mp3.GetPlayers())
overzicht = overzicht + "ID: " + Convert.ToString(player.id) + "\r\n" +
"Merk: " + player.make + "\r\n" + "Model: " + player.model +
"\r\n" + "MB-size: " + player.mBSize + "\r\n" + "Prijs: " +
player.price + "\r\n" + "\r\n";
return overzicht;
}
And Mp3.GetPlayers() is this:
private static ArrayList players = new ArrayList();
public static void Initialize()
{
Mp3Player player1 = new Mp3Player(1, "GET Technologies .inc", "HF 410", 4096, 129.95M, 500);
Mp3Player player2 = new Mp3Player(2, "Far & Loud", "XM 600", 8192, 224.95M, 500);
Mp3Player player3 = new Mp3Player(3, "Innotivative ", "Z3", 512, 79.95M, 500);
Mp3Player player4 = new Mp3Player(4, "Resistance S.A.", "3001", 4096, 124.95M, 500);
Mp3Player player5 = new Mp3Player(5, "CBA", "NXT Volume", 2048, 159.05M, 500);
players.Add(player1);
players.Add(player2);
players.Add(player3);
players.Add(player4);
players.Add(player5);
}
public static ArrayList GetPlayers()
{
return players;
}
I suspect the problem is you're never calling Mp3.Initialize(). You could add this to a static constructor in the Mp3 class:
private static List<Mp3Player> players = new List<Mp3Player>();
static Mp3()
{
Initialize();
}
// This can be private now...
private static void Initialize()
{
....
Note that you may want to change the ArrayList to a List<Mp3Player>, as well.
Also, as an aside, you should give StringBuilder and String.Format a try. Instead of this...
overzicht = overzicht + "ID: " + Convert.ToString(player.id) + "\r\n" +
"Merk: " + player.make + "\r\n" + "Model: " + player.model +
"\r\n" + "MB-size: " + player.mBSize + "\r\n" + "Prijs: " +
player.price + "\r\n" + "\r\n";
You can do:
StringBuilder overzicht = new StringBuilder();
overzicht.AppendLine(String.Format("ID: {0}", player.id));
overzicht.AppendLine(String.Format("Merk: {0}", player.make));
overzicht.AppendLine(String.Format("Model: {0}", player.model));
overzicht.AppendLine(String.Format("MB-size: {0}", player.mBSize));
overzicht.AppendLine(String.Format("Prijs: {0}", player.price));
return overzicht.ToString();
Much easier to read ;)
My String.Format isn't that compelling here... but if this was all on one line, it'd be much more useful:
return String.Format("ID:{0}, Merk:{1}, Model:{2}, MB-size:{3}, Prijs:{4}",
player.id, player.make, player.mode,
player.mBSize, player.price);
I’d like to create a method to replace delimiters for the intended target use (html email, log, database). The delimiters are constant so I’d like to be able to reference a object that maps recognizable names to string values (semicolon = “;”, htmlLineBreak = “<br/>”, etc.). Is there a better means to do this than this below?
public static class Utilities
{
public string ReplaceDelimiter(string content
, Delimiter currentDelimiter, Delimiter outputDelimiter)
{
return content.Replace(currentDelimiter.ToString()
, outputDelimiter.ToString());
}
}
public class Delimiter
{
public const string comma = ",";
public const string semicolon = ";";
public const string colon = ":";
public const string lineBreak = "\r\n";
public const string htmlLineBreak = "<br/>";
}
Edited following comments:
A use case would be when I want to log an error to different targets and send the same contents (formatted differently) in an email. The log may go to a database column (want key/value with semicolon delimiter) or log file (want delimiter to be line breaks). The email would be HTML so want the delimiter to be replaced with <br/>.
Below would be an excerpt from a logging method that has a few parameters including the actual Exception:
StringBuilder delimitedMessage = new StringBuilder();
delimitedMessage.Append("Date=" + DateTime.Now.ToShortDateString() + ";");
delimitedMessage.Append("Time=" + DateTime.Now.ToLongTimeString() + ";");
delimitedMessage.Append("Source=" + objException.Source.ToString().Trim() + ";");
delimitedMessage.Append("Method=" + objException.TargetSite.Name.ToString() + ";");
delimitedMessage.Append("Erring Method=" + methodName + ";");
delimitedMessage.Append("Computer=" + System.Environment.MachineName.ToString() + ";");
delimitedMessage.Append("Log Message=" + logMessage + ";");
delimitedMessage.Append("Exception Error=" + objException.Message.ToString().Trim() + ";");
delimitedMessage.Append("Severity=" + severity.ToString() + ";");
delimitedMessage.Append("Stack Trace=" + objException.StackTrace.ToString().Trim() + ";");
contentToLog = delimitedMessage.ToString();
WriteToDb(contentToLog);
WriteToLog(Utilities.ReplaceDelimiter(contentToLog, Delimiter.semicolon, Delimiter.lineBreak));
SendEmail(Utilities.ReplaceDelimiter(contentToLog, Delimiter.semicolon, Delimiter.htmlLineBreak));
Code
public class Delimiter {
public static readonly Delimiter
HtmlLineBreak=new Delimiter {
Value="<br/>"
},
LineBreak=new Delimiter {
Value="\r\n"
},
Semicolon=new Delimiter {
Value=";"
},
Colon=new Delimiter {
Value=":"
},
Comma=new Delimiter {
Value=","
};
public override String ToString() {
return Value;
}
public String Value {
get;
set;
}
}
Test
var t=Utilities.ReplaceDelimiter("123\r\n", Delimiter.LineBreak, Delimiter.HtmlLineBreak);
Debug.Print("{0}", t);
Output
123<br/>