Im trying to get the class variable name
static void Main()
{
TaskAction m_first = new TaskAction();
m_first.Increment();
m_first.Increment();
TaskAction m_Second = new TaskAction();
m_Second.Increment();
}
public class TaskAction
{
private int m_Current;
public TaskAction()
{
m_Current = 0;
}
public void Increment()
{
m_Current++;
write(" TaskAction " + vairableName + " " + m_Current);
}
}
i want to it to write out:
TaskAction m_first 1
TaskAction m_first 2
TaskAction m_second 1
Retrieving metadata about your program like that is both complex and unnecessary, just add the name by passing it to the constructor.
static void Main()
{
TaskAction m_first = new TaskAction("m_first");
m_first.Increment();
m_first.Increment();
TaskAction m_Second = new TaskAction("m_Second");
m_Second.Increment();
}
public class TaskAction
{
private int m_Current;
private string m_taskName;
public TaskAction(string taskName)
{
m_taskName = taskName;
m_Current = 0;
}
public void Increment()
{
m_Current++;
write(" TaskAction " + m_taskName + " " + m_Current);
}
}
Short Answer: You can't.
Long Answer:
Technically, it's possible to determine a variable name by inspecting the IL (the intermidate language created by the C# compiler), but this operation is hard and error-prone. Also, you ignore some important questions:
First of all, as already asked here: Why? how such thing will enhance your program?
Each instance of the class can have multiple variables pointing to it (see my answer about types in .NET here). Which of them you want to get? For example, consider the following program:
var v1 = new TaskAction();
var c2 = new TaskAction();
c1.Increment(); // 1 c1
c2 = c1;
c2.Increment(); // 2 c1? 2 c2? 2 c1 c2?
By doing so, you break the encapsulation in a difficult way - any reflection breaks the encapsulation, and really don't use it unless you really need it - but so much? Reflection breaks the hidden information about the private interface, you question breaks the internal interface!
Since you didn't give enough information, I can't know why you tought you need that. But here is some solutions:
If you want, for example, logging with categories - simply pass the category to the constructor, as sugegsted above.
If you want to know which type the variable is - using its name is very very very bad approach, even though you have conventions - use polymorphism instead (best), or, at least, check the type with is/as, for example:
if (this is Drived)
{
((Drived)this).SomeDrivedMethod();
}
Note that it breaks the OOP principles: a class shouldn't know about its drived classes.
Hope this helped you. Have a nice day!
Edit:
For your purpose, you can do one of the following:
Best - debug your code, see the call stack etc.
Worse - print the caller method name, instead of the object name. It's can be done using System.Runtime.CompilerServices.CallerMemberNameAttribute:
void Increment([System.Runtime.CompilerServices.CallerMemberName] string caller = null)
{
// Default value to `caller` is neccessary
// ...
Console.WriteLine("Caller: {0}", caller);
}
Note: the compiler fills the caller parameter, not in runtime.
Get object.GetHashCode() if you want to uniquely identify class object or provide name to class by using custom constructor.
Related
I want to pass a delegate declaration to a class that will later be assigned by a different class and then later invoked by the first class. I get a NullReferenceException at the line indicated in the code below. How can I change the code to get the desired behavior?
class FirstClass
{
public Func<bool> funct;
public FirstClass(Func<bool> funct)
{
this.funct = funct;
}
public void callFunc()
{
funct.Invoke(); // NullReferenceException
}
}
class Program
{
public static Func<bool> testFunction;
static void Main(string[] args)
{
FirstClass firstClassInstance = new FirstClass(testFunction);
var secondClassInstance = new SecondClass();
firstClassInstance.callFunc();
}
}
class SecondClass
{
public SecondClass()
{
Program.testFunction = isManipUnderCursor;
}
private bool isManipUnderCursor()
{
return true;
}
}
If you want to invoke whatever is the current value of Program.testFunction, invoke Program.testFunction
public void callFunc()
{
Program.testFunction?.Invoke();
}
Or you provide a code that changes the value of what FirstClass.funct is, and call that:
class FirstClass{
...
public void ChangeFuncTo(Func<bool> newFunc){
funct = newFunc;
}
...
}
FirstClass firstClassInstance = new FirstClass(testFunction);
var secondClassInstance = new SecondClass();
firstClassInstance.ChangeFuncTo(Program.funct);
This whole thing you've arranged is fairly terrible in terms of structure, encapsulation and coherent class responsibilities. It would be good if you could post an actual use case for what the true aim is, so we can advise, but in general you should treat funcs like data; if you only know what operation you want firstclass's func to perform after you have finished constructing and using some other object, don't rely on a static to pass the new func around; provide and call a method on the first class to set the new behavior. Strive to find ways of avoiding static in your code.
//we need to make FirstClass for some reason, before we can generate the fun it will use
FirstClass firstClassInstance = new FirstClass();
//second class is a func generator
var secondClassInstance = new SecondClass();
//now we can generate the func and set it
firstClassInstance.ChangeFuncTo(secondClassInstance.GetNewFunc());
Or
//second class is a func generator, it can generate before firstclass is made
var secondClassInstance = new SecondClass();
//now we can generate the func and set it
FirstClass firstClassInstance = new FirstClass(secondClassInstance.GetFunc());
In C# you can't "change what some simple variable points to, by changing what some other simple variable points to". To explain it in simpler terms of good old data:
string first = "this is the first string";
string second = first
first = "something else";
second will still refer to that value of "this is the first string". When you establish extra references, they don't chain. When you write string first = "this is the first string"; it gives us memory like this:
first --> "this is the first string"
Then you write string second = first which gives us memory like this:
first --> "this is the first string" <-- second
Finally you write first = "something else" which gives us memory like:
"this is the first string" <-- second
first --> "something else"
Changing first never affected second. When writing string second = first you don't end up with chained references in memory, like this:
second --> first --> "this is the first string"
such that altering first would cause second to see it:
second --> first --. //"this is the first string" garbage collected
`-> "something else"
When you pass testFunction to FirstClass, it is null because testFunction has not been initialized or assigned. In this case, the reference passed doesn't point to the future home of the value, but it points to null and always will.
I'm generating a random number from 1-1000. I have 200 functions named function1, function4, function 10, function 11, etc. What I would like to do is execute a specific function depending on if the number generated requires a function, and ignore it if not.
My first thought was to create an int[] containing all of the values that would trigger a function, and if the int[] contains the random number to use if statements to figure out what the number is. I'm concerned that it must be a really crude solution to an easy problem though.
I know the "best way" to do something is subjective, but is there a better way to accomplish this?
UPDATE: As per comments, I should probably have started out by pointing out that doing this for 200 functions is probably a good sign that there is some serious issue in your design. This is probably an XY question where you are trying to solve a problem in some crazy way and asking about your intended solution instead of asking about the problem itself.
That said I'll leave the original answer because it's still good advice when mapping a reasonable amount of function calls that can/will change during the life cylce of your app or dynamically as the code runs.
I won't get into why you are doing this, but I'll try to at least point you in the right direction so this doesn't become a complete nightmare when you need to modify/expand behavior:
You can map numbers to function calls using delegates and a dictionary. Assuming your functions take no arguments and return void you'd do:
var functionsMap = new Dictionary<int, Action>();
//map functions
var r = getSomeRandomNumber();
if (functions.TryGetValue(r), out var a)
a(); //invoke function
Mapping functions is simply adding keys and values:
functionsMap.Add(1, () => function1());
functionsMap.Add(3, () => function3());
//etc.
If your functions take arguments or return values, you'd use the adequate delegate: Action<T>, Func<T1, T2> etc.
You can use reflection to invoke appropriate method:
Type exampleType = exampleObject.GetType();
MethodInfo exampleMethod = exampleType.GetMethod(methodName);
exampleMethod.Invoke(this, null);
Where methodName can be created using your random number.
Without commenting on the wisdom of having 200 functions named the way yours are, you can use reflection to determine whether a given functionX() exists, like so:
public void ExecuteDynamicMethod(int number)
{
// Modify these two lines with your app's dll/exe and class type:
Assembly assembly = Assembly.LoadFile("...Assembly1.dll");
Type type = assembly.GetType("YourClassType");
if (type != null)
{
MethodInfo methodInfo = type.GetMethod("function" + number);
if (methodInfo != null)
{
object classInstance = Activator.CreateInstance(type, null);
methodInfo.Invoke(classInstance, null); // null = "no function arguments"
}
}
}
This can then be called for a given value like
ExecuteDynamicMethod(14);
See this SO answer for the inspiration behind this.
Reflection can be used for this purpose. I want to give and keep below example for not only the objective of the question but also for future reference. Also, of course that many function is not good but below code shows the approach that can work with many functions if they have similar name (like starting with "function" keyword).
Assume below is Methods.cs
using System;
using System.Reflection;
namespace YourMethodNamespace
{
public class YourMethodClass
{
public void function1()
{
Console.WriteLine("Function-1");
}
public void function2()
{
Console.WriteLine("Function-2");
}
...
public void function200()
{
Console.WriteLine("Function-200");
}
public static void invokeMethodsDynamically(int randomNumber){
Type yourClassType = typeof(YourMethodClass);
ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(Type.EmptyTypes);
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{});
//If the constructor has parameters, then we can pass them by this way. Like below;
/*ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(new[]{typeof(int)});
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{3});
*/
MethodInfo[] methodInfoArr = yourClassType.GetMethods();
foreach(MethodInfo methodInfo in methodInfoArr){
if(methodInfo.Name == "function" + randomNumber){
methodInfo.Invoke(yourClassObject, null);
}
}
}
}
}
Let's say below is Program.cs
using System;
using YourMethodNamespace;
namespace YourProgramNamespace
{
public class YourProgramClass
{
public static void Main()
{
Random random = new Random();
int randomNumber = random.Next(1, 201);
//If Methods.cs is in another Assembly
/*string pathToDllAssembly = #"Domain.dll";
Assembly dllAssembly = Assembly.LoadFrom(pathToDllAssembly);
Type methodsClassType = dllAssembly.GetType("YourMethodNamespace.YourMethodClass");
ConstructorInfo methodClassConstructorInfo = methodsClassType.GetConstructor(Type.EmptyTypes);
object methodsClassObject = methodClassConstructorInfo.Invoke(new object[]{});
MethodInfo methodInfo = methodsClassType.GetMethod("invokeMethodsDynamically");
methodInfo.Invoke(methodsClassObject, new object[]{randomNumber});
*/
YourMethodClass.invokeMethodsDynamically(randomNumber, null);
}
}
}
Also for testing and observing, below link can be used.
https://repl.it/#erdsavasci/ReflectionTest
Greeting fellow programmers!
I am currently studying software development (I started not a month ago) and I have a problem that needs a solution. Underneath you can find the code and as you can see, the method WriteNumber needs help. I need to write the code in a way that when I run the program, on the console screen the following two lines will be shown:
Hello World!
81
The Main method code cannot be changed and also I cannot add more methods to the class Calculator so the code needs to be done only within the WriteNumbers method. I have tried a lot of things but I am still grasping how everything works so any help is welcome! Thank you in advance for your time.
Namespace CalculatorTest
{
class Calculator
{
public static string WriteText (string input)
{
return "" + input;
}
public static string WriteNumber()
{
}
}
class Program
{
static void Main(string[] args)
{
string s = Calculator.WriteText("Hello World!");
Console.WriteLine(s);
string n = Calculator.WriteNumber(53 + 28);
Console.WriteLine(n);
Console.Read();
}
}
Not to do your homework for you to just be copied/pasted, hopefully I can give you some hints...
Notice how the method is being invoked:
Calculator.WriteNumber(53 + 28)
The 53 + 28 part happens first, then the result of that operation is passed to the method. That result, naturally, is 81. What's important about that is its type, which is an integer.
So, reasonably, the method signature needs to accept an int as a parameter. This would be done very similarly to how the other method accepts a string as a parameter:
public static string WriteText(string input)
What, then, does that method need to do with that input? Well, it's only a single value, so there aren't any calculations to be performed on it. It would appear that the method simply needs to return the value as a string. (It's your homework so you tell me, is that correct?)
This can be done with exactly two things:
Calling .ToString() on the value
Using the return keyword to return the result of that operation
(Note: The .ToString() operation does something very intuitive on value types, such as int or double or bool. As you progress into using reference types, you're going to find that it does something very different. Any time you have a custom class on which you want to call .ToString(), you'll need to override the .ToString() method on that class first.)
Please read David's answer, it's important that you make the effort to understand why this works the way it does. That being said:
public static string WriteNumber(int number)
{
return number.ToString();
}
Thank you all for your valuable input but special thanks to David because he showed where I made my error. I forgot that the two numbers in the main function will be summed up FIRST and THEN forwarded to the method in the class Calculator. After that got cleared up, it was easy to understand what to do (basically adjust the type of the input parameter to int).
namespace CalculatorTest
{
class Calculator
{
public static string WriteText (string input)
{
return "" + input;
}
public static string WriteNumber(int sumOfNumbers)
{
return "" + sumOfNumbers;
}
}
class Program
{
static void Main(string[] args)
{
string s = Calculator.WriteText("Hello World!");
Console.WriteLine(s);
string n = Calculator.WriteNumber(53 + 28);
Console.WriteLine(n);
Console.Read();
}
}
}
I have a logging class which creates an instance of log4net and I can call it from anywhere in my code. I also have a method to find out the class and method name of caller. here is my method:
private static string CurrentMethod()
{
StackTrace stackTrace = new StackTrace();
MethodBase method = stackTrace.GetFrame(2).GetMethod();
string cn = method.ReflectedType.Name;
string mn = method.Name;
string output = "[" + cn + "." + mn + "]";
return output;
}
i found these articles: link1, Link2, Link3, Link4 and so many others, but none of them discuss about the efficiency and performance.
now I have two questions:
1- can I use this method in a big project(about 1000 requests in one second)? I mean how much does this effect the project's efficiency and performance?
2- Os there a better way to write the above method?
Also here is part of my logging class. I guess it can help:
public static class Tools_Log
{
private static ILog logger;
public static ILog GetLogger()
{
return logger ?? (logger = CreateLogger());
}
private static ILog CreateLogger()
{
//Some log4net initialization
return LogManager.GetLogger("WebService");
}
private static string CurrentMethod()
{
StackTrace stackTrace = new StackTrace();
MethodBase method = stackTrace.GetFrame(2).GetMethod();
string cn = method.ReflectedType.Name;
string mn = method.Name;
string output = "[" + cn + "." + mn + "]";
return output;
}
public static string MessageForLogFile(string message, string exeption, double time)
{
string currentMethod;
string executiontime;
string consumer;
string body;
string output;
currentMethod = CurrentMethod();
executiontime = ExecutionTime(time);
body = BodyForLog(message, exeption);
consumer = Consumer();
output = OutPut(currentMethod, executiontime, consumer, body);
return output;
}
}
i call the log class like this:
Tools_Log.GetLogger().Info(Tools_Log.MessageForLogFile("some text", "some text", execution time));
Thanks.
Yes, reflection is always a slower process. If you want the name of the method you can get it quite easily with the CallerMemberNameAttribute. Add a string parameter with an empty default value, and apply that attribute to it, and the compiler will send the name for you.
Also, if you're looking for fast logging, take a look at ETW instead of Log4Net.
Here: https://msdn.microsoft.com/en-us/library/windows/desktop/bb968803(v=vs.85).aspx
And Here: http://blogs.msdn.com/b/vancem/archive/2012/07/09/logging-your-own-etw-events-in-c-system-diagnostics-tracing-eventsource.aspx
EDIT:
As for your question in the comments, unfortunately, you can't get the name of the method 2 levels up, at least, not directly. CallerMemberName is basically just syntax sugar, it tells the compiler to take the name of the calling member, and place it in the parameter, so it works on a single level. However, since it relies on default parameters to do so, if you send the parameter manually, the CallerMemberName functionality doesn't apply, so you can do something like this:
public void UserMethod()
{
IntermediaryMethod();
}
public void IntermediaryMethod([CallerMemberName] caller = "")
{
LogMethod(caller)
}
public void LogMethod([CallerMemberName] caller = "")
{
// Log...
}
If you pass a value by yourself, it won't be overridden, so doing something like this will allow you to get the name of the caller from 2 levels up, while retaining the functionality for a single level.
Performance must be measured and this is done using profilers.
BTW, maybe instead of using StackTrace class, you can use caller information attributes introduced in .NET 4.5.
While [CallerMemberName] attribute doesn't provide class name, [CallerFilePath] provides the full path to the source code file where the caller member is defined (it might be even better for debugging/logging purposes since you know where to investigate a possible bug or error).
I am sure am messing around with a lot of casting and such in this code below. It seems like there should be a smoother way. I'm basically trying to use a builder method (CreateNewPattern) to handle creating new objects of the passed sub-class type (by the CreateNewCircularPattern and CreateNewLinePattern methods). I presently only have two sub-classed types CircularHolePattern and SingleLineHolePattern that inherit from HolePattern, but I expect to have more as my app grows.
Is this a place for using a delegate or a lambda? It know nothing about them, so please be as specific as possible with and code suggestions.
private CircularHolePattern CreateNewCircularPattern()
{
var CreatedPattern = CreateNewPattern(typeof(CircularHolePattern));
return (CircularHolePattern)CreatedPattern;
}
private SingleLineHolePattern CreateNewLinePattern()
{
var CreatedPattern=CreateNewPattern(typeof(SingleLineHolePattern));
return (SingleLineHolePattern)CreatedPattern;
}
private HolePattern CreateNewPattern(Type PatternTypeToCreate)
{
var NewHolePattern = (HolePattern)Activator.CreateInstance(PatternTypeToCreate);
NewHolePattern.PatternName = "Pattern #" + (HolePatterns.Count + 1).ToString();
this.AddPattern(NewHolePattern);
this.SetActivePattern(NewHolePattern);
return NewHolePattern;
}
I suspect you want generics:
private T CreateNewPattern<T>() where T : HolePattern, new()
{
var newHolePattern = new T();
newHolePattern.PatternName = "Pattern #" +
(HolePatterns.Count + 1).ToString();
this.AddPattern(newHolePattern);
this.SetActivePattern(newHolePattern);
return newHolePattern;
}
private SingleLineHolePattern CreateNewLinePattern() {
return CreateNewPattern<SingleLineHolePattern>();
}
private CircularHolePattern CreateNewCircularPattern() {
return CreateNewPattern<CircularHolePattern>();
}
The T is the generic-type-argument; the type we want to create. The where says "it must be HolePattern or a sub-type, and it must have a public parameterless constructor" - this lets us use new T() to create a new instance of it, and access all members of HolePattern against such instances (such as PatternName). This also allows us to call the methods that accept a HolePattern as an argument.
For one, you could reduce the Create...Pattern methods to
private CircularHolePattern CreateNewCircularPattern()
{
return CreateNewPattern(typeof(CircularHolePattern));
}
Another suggestion might be to only work in abstractions. For example, only return HolePattern types from the Create...Pattern methods instead of their concrete types such as CircularHolePattern. You are casting them down to HolePattern in any case.
So, CreateNewCircularPattern becomes
private HolePattern CreateNewCircularPattern()
{
return CreateNewPattern(typeof(CircularHolePattern));
}