PHP has a function called print_r() and var_dump() that will display all the contents of an item. It makes it very easy to figure out what things are.
Is there something like that in C#?
I know there is a Console.WriteLine("Hello"); in C#, but does this work in the MVC? Can I do some type of debug.trace() like flash does into a debug console while I run the application?
System.Diagnostics.Debug.WriteLine("blah");
and in order to show all variables in the object you would have to override its ToString() method or write a method which returns all the info you need from the object.
i.e.
class Blah{
string mol = "The meaning of life is";
int a = 42;
public override string ToString()
{
return String.Format("{0} {1}", mol, a);
}
}
System.Diagnostics.Debug.WriteLine(new Blah().ToString());
In short there is nothing in built but it can be done.
If you must print ALL the objects info without overriding or adding logic on a class by class level then you are in the realms of reflection to iterate the objects PropertInfo array
Related
I just learned about delegates and the publisher/subscriber pattern, however I have been having some problem implementing them in my current code, mainly because Im not sure what should be assign to what(I shall explain this).
I have a class, example Class A. It is a library class that contains codes that write logs into .txt file. I would like to be able to take these logs and write them somewhere else, example another .txt file/TextBox/RichTextBox.
Class A
//Just a library class for log functions
//Declare and instantiate the delegate
public void delegate myDel(string message)
public myDel customDel, customDel2
LogCategory(string category)
{
//Bunch of codes that separates the log into category Info/Warn/Error
WriteLog()
}
WriteLog()
{
StreamWriter sw = new StreamWriter(LogFilePath)
//writes logs into .txt file1
}
then in a separate class
Class B
//This is the main program where all the logs are written
public void PrintLog(string message)
{
Class A ca = new Class A();
ca.LogCategory();
}
public void delegateTheLogs()
{
//how do I use customDel to write the logs to another text file in a
//different directory
}
The idea is that delegate is suppose to:
act as a pointer
allow the program to write logs to multiple destination at the same time
The question is what do I use customDel for and how do I use it catch the logs and write them somewhere?
I think this is an interesting topic, and if anyone knows how to do this, please help me figure this out.
Oh and Im not interested in using events, I know delegate and events are pretty common to use together.
Thanks
Following on from my comment, here's an example. We have a class called FlexibleLogger that basically knows how to format stuff that it is given but it doesn't have any baked in ability to write the log data to anywhere, the idea being that the code that creates the logger also creates the routine that the logger will use to output:
public class FlexibleLogger{
Action<string> _logWriterAction;
public FlexibleLogger(Action<string> logWriterAction){
_logWriterAction = logWriterAction;
}
public Log(string message){
_logWriterAction($"{DateTime.UtcNow}: {Message}");
}
public Log(Exception ex){
Log(ex.Message);
}
}
This class doesn't know how to write a file, or console, or post the message to a web service, or email it, or put it in a rabbit queue etc.. all it knows how to do is formulate a log message provided into having a time at the start, or pull the message out of an exception(and then pass it to the method that puts a time at the start), and then call the Action (a neater way of declaring a delegate that takes arguments of various types and returns no value) passing in the message
The Action is some variable(able to be varied) method created by you
We might use it like this:
public class Program
{
public static void Main()
{
//it's a "local function", IMHO a neater way of providing a method that can be passed as an action
void consoleWriterFunc(string f){
Console.WriteLine(f);
};
//see the thing we pass as the Action parameter is a method/function,
//not a data item like a string, int, Person etc
var logger = new FlexibleLogger(consoleWriterFunc);
//log will make a string like "12-Dec-2020 12:34:56: a"
//and invoke the consoleWriterFunc, passing the string into it
//in turn it prints to the console
logger.Log("a");
//how about a logger that writes a file?
void fileWriterFunc(string f){
File.AppendAllText("c:\\temp\\some.log", f);
};
logger = new FlexibleLogger(fileWriterFunc);
logger.Log(new Exception("something bad happened"));
}
}
Doesn't have to be a local function, you can pass any method at all that takes a string and returns a void, as your Action<string>. It doesn't even have to be a method you wrote:
var sw = new System.IO.StringWriter();
var logger = new FlexibleLogger(sw.Write);
logger.Log("I'm now in the string writer" );
Microsoft wrote the method StringWriter.Write- it takes a strong, returns a void and calling logger.Log having passed the Write method of that stribgwriter instance means that the logger will Log into the stringwriter (a wrapper around a stringbuilder)
Hopefully this helps you understand that a delegate is "just a way to make a method into something you can pass as a parameter, just like anything else. They've been available for years, if you think about it, manifested as events. Microsoft have no idea what you want to do when you click a button, so they just have the button expose an event, which is really just a collection of delegates; a List of methods that the button should call when it's clicked.
I do almost all of my programming in VB.net (all flavors). I am now been assigned a task to make a new routine in an existing C# application. What I want to be able to do is pass a string variable to a class where I can figure out device type of a symbol handheld and figure out where an executable resides on device.
I am trying to keep the class to contain changes we make going forward in one place.
so a brief description is on a screen there will be a button. on that button click I want pass the text of the button to a (what would be a module in VB) a class and depending on text being passed and device type call a separate executable that lives on the device.
Everything I have tried so far has thrown errors.
On my button click i have
String Reponse = clsCallAction("Activity");
but that gets a message that clsCallAction is a type but is used like a variable.
here is the smaple of clsCallaction
internal static partial class clsCallAction
{
public static object GetPath(object lAppName)
{
string resp = "";
if (lAppName.Equals("Activity"))
{
resp = #"\application\activity.exe";
}
return resp;
}
}
If I put new in front of the clsCallAction("Activity") on button click I get a
cannot create instance of the static class 'clsCalACtion'
appreciate any pointers. very new at C#
It would look something like this:
public static class CallAction
{
public static object GetPath(object lAppName)
{
string resp = "";
if (lAppName.Equals("Activity"))
{
resp = #"\application\activity.exe";
}
return resp;
}
}
And would be used like this:
String Reponse = CallAction.GetPath("Activity");
Don't prefix classes with cls
Avoid using object if possible - it just makes everything harder work than it needs to be.. Kinda like calling everything "thing" - ("Put the thing in the thing and open the thing" is harder to understand than "put the key in the lock and open the door")
My class requires additional information to properly output its status, so I've added a custom PrintSelf method taking the appropriate parameters.
However, I'm afraid there are still calls to ToString in my large project, which were not replaced by the new method. How can I find those improper calls to ToString?
I'm using VS 2015, but it does not seem to have this ability.
Throwing an exception in ToString would be an obvious way, but I don't want to do that for two reasons:
ToString can still perform a different job and output something not depending on the added parameter.
There is no way to get full code coverage, meaning it would only find a few instances of implicit calls, but not (reliably) all of them.
To override ToString and log the caller you can do like this
public override string ToString()
{
StackTrace stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames();
StackFrame callingFrame = stackFrames[1];
MethodInfo method = callingFrame.GetMethod();
YourLogingMethod(method.DeclaringType.Name + "." + method.Name);
return base.ToString();
}
You can make usage of the Obsolete Attribute :
public class MyFirstClass
{
//true or false parameters indicates whether to throw
// a compile error (true) or warning (false)
[Obsolete("Please use the method PrintSelf() instead of ToString()", false)]
public overrides string ToString()
{
//Whatever code you want here
return "";
}
}
public class MySecondClass
{
public void Test()
{
mfc = new MyFirstClass();
mfc.ToString(); //Here you will get a compiler warning
}
}
So this will let you know inside Visual Studio of all the calls made to this function. Since it is only a warning, it is still possible to use it.
(note : Sorry if the syntax is not correct, I'm normally a VB .Net developper, feel free to correct it if needed.)
I would like to implement what I know as a CVAR System, I'm not entirely sure on what the official name of it is (if any).
It's essentially a system used in some programs and video games, where a user can pull down a console and input a command, such as "variable 500" to set that variable to 500. Instances of this can be found in any Half-Life game, Doom and Quake games, and many more. The general idea seems to be to hide the underlying architecture, but still allow protected access, for instance, one may be able to view the value for, say, gravity, but not change it. Some of these values may also be functions, for instance, a user may be able to input "create " to create an enemy type at their location, or some other location specified.
Looking through the Half Life 2 SDK, and from what I remember on the GoldSrc SDK, it seems like they at least implemented "flagging" of sorts, where certain commands would only work under certain conditions, such as if another value was set, or if the user has some permission level.
My initial thought was to create a Dictionary, or an object similar to do that, and use that to bind string values to function delegates, as well as keep a "protection" level of sorts, to limit usage of certain commands. However, this seems rather cumbersome, as I believe I would have to go through and add in a new entry manually for each value or function I wanted to implement. I also don't know if this would give me the control level I'm looking for.
I believe ideally what I would like would be a CVAR System class, as well as a Register function that can take it say, a variable/function delegate, a string to access it, and whatever protection level I need. This way I can add what I need as I see them, so everything is still in it's related classes and files.
I'm really just looking for some ideas here, so my questions are:
Has anyone ever done something like this before, and if so, how?
Would my implementation work? (Theoretically, if not, can you think of a better way?)
If someone is more knowledgeable with how one of the previously mentioned titles does it, can you elaborate on that a bit? It seems to be hard to find documentation on them.
I'm not really looking for specific code, just more of structuring design. And it doesn't have to be "commercial" or work just like another, I just need something to get me going.
Were you thinking about something like this?
class CVAR
{
[ProtectionLevel(CVARFlags.InGameOnly | CVARFlags.Admin)]
private float gravity = 0.1f;
[ProtectionLevel(CVARFlags.InGameOnly | CVARFlags.Admin)]
private float friction = 0.1f;
[ProtectionLevel(CVARFlags.ReadOnly)]
private string serverVersion = "x.x.x";
public void SetCVARValue(string commandLine) {
string cvarName = GetCvarName(commandLine); // parse the cmd line and get the cvar name from there
object cvarValue = GetCvarValue(commandLine); // parse the value from the string
FieldInfo field = typeof(CVAR).GetField(cvarName);
object[] attributes = field.GetCustomAttributes(typeof(ProtectionLevel), false);
if(attributes.Length > 0) {
ProtectionLevelAttribute attr = (ProtectionLevelAttribute)attributes[0];
if(attr.CheckConditions(World.Instance)) {
field.SetValue(this, cvarValue);
} else {
// error report
}
}
}
}
You could write a parser that looks for commands like
/object_property value
/object_method arg1 arg2
A dictionary, like you suggested, could map those strings to properties and functions. The creation of the dictionary could be done dynamically using reflection by looping through eligible objects, taking their public methods and accessors, and generating a string for them.
Then the dictionary could be mapped in a class for convenience and error checking.
For the methods, the dictionary values could be delegates that take 0..n arguments, for the properties/fields, you will need to be able to some data binding between your actual fields and the dictionary value. UNLESS, your objects themselves refer to the dictionaries for their values, in which case the values only live in place.
To do so, you could simply register your properties using reflection in the object constructor, then call the dictionary in your properties.
[Flags]
public enum CVarAccessibilities
{
Settable,
Gettable
}
public class CVar<T>
{
public CVarAccessibilities Accessibility { get; set; }
T val;
public T Value {
get { return val; }
set
{
if (!Accessibility.HasFlag(CVarAccessibilities.Settable))
return; // just don't set it, maybe print some warning
val = value;
}
}
}
public static class CVarRegistry
{
static Dictionary<string, Object> CVars;
static CVarRegistry { /* use reflections to initialize the dictionary */ }
public static T GetValue<T>(Type owner, string paramName)
{
CVar cvar;
if (!CVars.TryGetValue(owner.Name + "_" + paramName, out cvar)
throw new MyCustomException();
return (T)cvar.Value;
}
public static void SetValue<T>(Type owner, string paramName, T value)
{
CVar cvar;
if (!CVars.TryGetValue(owner.Name + "_" + paramName, out cvar)
throw new MyCustomException();
cvar.Value = value;
}
}
public class MyObject
{
public static int MyRegisteredValue
{
get { return Global.CVarRegistry.GetValue<int>(typeof(MyObject), "MyRegisteredValue"); }
set { Global.CVarRegistry.SetValue(typeof(MyObject), "MyRegisteredValue"); }
}
}
Hope that helps!
This is more commonly known as 'tweak' variables.
Good discussion here: https://gamedev.stackexchange.com/questions/3631/tweaking-and-settings-runtime-variable-modification-and-persistence
I just started using C# this afternoon, so be a little gentle.
Currently I am working on a type of "template engine" where one of the callbacks needs to generate a globally unique ID. I am using delegates to manage the callbacks.
Currently the code looks like this (though I have also tried an anonymous function & returning NewGuid directly w/o a variable):
static string UID(List<string> p)
{
string s = Guid.NewGuid().ToString();
return s;
}
Which, when called directly, works fine. However if I try to call it via the delegate (added to a StringDictionary via addCallback("generate UID", new CallbackWrapper(UID))), the program will generate the same GUID regardless of how many times I duplicate it; even though calling the method directly both before & after the event occurs results in a unique ID as expected. I'v
No doubt it's just something simple I've missed, inevitably stemming from me being relatively inexperienced at C#.
Any help would be appreciated.
Thanks.
Well, I've now tried Dictionary with the same result.
CallbackWrapper is just the delegate, it's defined like this:
delegate string CallbackWrapper(List<string> parameters);
The remainder of the work is done in another class, which looks like this:
class TemplateParser
{
private Dictionary<string, CallbackWrapper> callbackMap;
public TemplateParser(string directivePrefix, string directiveSuffix)
{
...
callbackMap = new Dictionary<string,CallbackWrapper>();
}
public TemplateParser() : this("<!-- {", "} -->") {}
{
callbackMap.Add(name, callback);
}
public string parse(string filename)
{
...
string replacement =
callbackMap[directiveName](new List<string>(parameters.Split(new string[] { ";", " " }, StringSplitOptions.RemoveEmptyEntries));
...
}
}
I've stripped out the majority of the string handling code to save some space.
The issue is in your calling code, not in the code itself, nor in the delegate.
Using delegates here definitely works if called correctly.
Furthermore, your code can be slightly simplified:
static string UID(List<string> p)
{
return Guid.NewGuid().ToString();
}
(The variable is utterly redundant.)
use delegate.invoke
The difference between direct function call and delegate.invoke is here
http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/f629c34d-6523-433a-90b3-bb5d445c5587
StringDictionary will automatically cast your CallbackWrapper to a string, meaning it will only run once and store the output of CallbackWrapper.ToString(). This is probably not what you want.
Try using Dictionary<string, CallbackWrapper> instead.