How can I find out who is (implicitly) calling my ToString? - c#

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.)

Related

it is possible to get stacktrace of methods calls inside call method?

I want to add more info to the logger at the call method level, and i need to know if exist possibility to get StackTrace of methods calls inside call method.
UPDATE: The purpose of this is to draw the flow of all methods called until the certain step inside call method.
EXAMPLE:
public class Type1
{
internal string method2_T1() {
return new Type2().method1_T2();
}
}
public class Type2
{
public string method1_T2()
{
return "Type2.method1_T2";
}
}
static void Main(string[] args)
{
string t = new Type1().method2_T1();
LogNow();
....
}
and the result to obtain, when I call LogNow(), are:
StackTrace of method2_T1()
...
Thanks
It's pretty easy:
var stackTrace = new StackTrace(true);
var traceToLog = stackTrace.ToString();
The true argument says to include the file info.
Todd Sprang's answer is good as the actual answer, but be aware that the stack trace will change in unpredictable ways when you move to a RELEASE build, or use async/await. Don't rely programatically on the answers because you may come unstuck when you put the code into production.
If you want to know the direct caller of a particular function, in a way Microsoft recommend, there's the useful trick using the [CallerMemberName], [CallerFilePath], and [CallerLineNumber] attributes. Mark up optional parameters like so;
public void LogWithCallerInfo(
string message,
[CallerMemberName] string memberName = "Caller",
[CallerFilePath] string sourceFilePath = "File",
[CallerLineNumber] int sourceLineNumber = 0)
{
WriteProgressMessage(..., memberName, sourceFilePath, sourceLineNumber);
}
and call like this;
LogWithCallerInfo("my message");
The three optional parameters will be replaced with the appropriate call info.

How to fake an object in NSubstitute and ignore its method's internal implementation?

I'm new to NSubstitute and trying to fake an existing class named OrgDataWS. This class has a method named GetDataSet:
public XmlElement GetDataSet(int token)
{
string perfLogMessage = string.Format("Org.GetDataSet: {0}", Guid.NewGuid().ToString());
MultiMessagePerformanceCounter performanceCounter = MultiMessagePerformanceCounter.StartNew(perfLogMessage);
XmlElement result = orgDataManager.GetDataSet(token);
performanceCounter.Stop();
return result;
}
The following is my test methods:
[TestMethod]
public void GetDataSetTest()
{
var dataWSStub = Substitute.For<OrgDataWS>();
var orgManagerStub = Substitute.For<OrgDataManager>();
var document = new XmlDocument();
var xmlElement = document.CreateElement("a");
orgManagerStub.GetDataSet(Arg.Any<int>()).Returns<XmlElement>(xmlElement);
dataWSStub.OrgDataManager = orgManagerStub;
var result = dataWSStub.GetDataSet(99);
}
However, when I run my test methods, this line
orgManagerStub.GetDataSet(Arg.Any<int>()).Returns<XmlElement>(xmlElement);
threw an exception. This exception is from the implementation of OrgDataManager class, from my understanding, this is not supposed to happen. The purpose of using that clause is that I hope if the orgManagerStub's DataDataSet method is invoked with any Int parameter, just return my xmlElement instance. I didn't hope my code to run the detailed implementation of OrgDataManager.
What's wrong with my test code? How to fix it?
As per the documentation:
Warning: Substituting for classes can have some nasty side-effects. For starters, NSubstitute can only work with virtual members of the class, so any non-virtual code in the class will actually execute! If you try to substitute for your class that formats your hard drive in the constructor or in a non-virtual property setter then you’re asking for trouble. If possible, stick to substituting interfaces.
(my emphasis)
The declaration you showed is not virtual, so the solution is to either create an interface for it, and substitute for that, or at least make that method virtual (and possibly other methods as well).

MakeGenericMethod/MakeGenericType on Xamarin.iOS

I'm trying to figure out what the limitations really means when deploying for iOS from Xamarin.
http://developer.xamarin.com/guides/ios/advanced_topics/limitations/
I was under the impression that you have no JIT and thus any MakeGenericMethod or MakeGenericType would NOT work as that would require JIT compilation.
Also I understood that when running on the simulator, these restrictions does not apply since the simulator is not running in the full AOT (Ahead of Time) mode.
After setting up my Mac so that I could deploy to my phone, I would except the following test to fail when running on the actual device (iPhone).
[Test]
public void InvokeGenericMethod()
{
var method = typeof(SampleTests).GetMethod ("SomeGenericMethod");
var closedMethod = method.MakeGenericMethod (GetTypeArgument());
closedMethod.Invoke (null, new object[]{42});
}
public static void SomeGenericMethod<T>(T value)
{
}
private Type GetTypeArgument()
{
return typeof(int);
}
The thing is that completes successfully and I can't really understand why. Does not this code require JIT compilation?
In an effort to "make it break" , I also did a test with MakeGenericType.
[Test]
public void InvokeGenericType()
{
var type = typeof(SomeGenericClass<>).MakeGenericType (typeof(string));
var instance = Activator.CreateInstance (type);
var method = type.GetMethod ("Execute");
method.Invoke (instance, new object[]{"Test"});
}
public class SomeGenericClass<T>
{
public void Execute(T value)
{
}
}
How can this work when there is no JIT?
Am I missing something ?
In order to make the code fail go to iOS project options, tab "iOS Build" and change the "Linker Behavior:" to "Link all assemblies". Running the code will result in Exception and it will be of type default constructor for type XXX was not found.
Now, make a reference to the SomeGenericClass{string} in your code and the method will run just fine. The two added lines cause the compiler to include SomeGenericClass{string} in the binary. Note that the lines can be anywhere in the application that is compiled into the binary, they don't have to be in the same function.
public void InvokeGenericType()
{
// comment out the two lines below to make the code fail
var strClass = new SomeGenericClass<string>();
strClass.Execute("Test");
var type = typeof(SomeGenericClass<>).MakeGenericType (typeof(string));
var instance = Activator.CreateInstance (type);
var method = type.GetMethod ("Execute");
method.Invoke (instance, new object[]{"Test"});
}

How get name of method in the method

I have a method. I want to check a condition and
if result of my condition is true throw new exception.
I need to name of method for message exception. For example :
public void MyMethod(Notifier not)
{
if(not.HasValue())
throw new Exception("MyMethod_name : " + not.Value);
}
How get name of method in the method?
Is this what you looking for?
new StackFrame(1, true).GetMethod().Name
but again playing with stack means performance hit if misused.
OR are you looking for this - http://www.csharp-examples.net/get-method-names/
OR http://heifner.blogspot.co.nz/2006/12/logging-method-name-in-c.html
OR have a look here nice notes - Get Calling function name from Called function
Hope this helps, cheers!
This approach avoids the stack issues:
public void MyMethod(Notifier not)
{
if(not.HasValue())
{
string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
throw new Exception(methodName + ": " + not.Value);
}
}
[But note that there may occasionally be unexpected results: for example, small methods or properties are often inlined in release builds, in which case the result will be the caller's method name instead.]
Using Reflection you can get the method name.....By using the powerful reflection facilities in the framework, you can invoke the method. This involves the System.Reflection namespace and theGetMethod method.
For implementation of Reflection, take a reference to this link......
http://www.dotnetperls.com/getmethod
public void MyMethod(Notifier not)
{
StackFrame stackFrame = new StackFrame();
MethodBase methodBase = stackFrame.GetMethod();
if(not.HasValue())
throw new Exception("MyMethod_name : " + methodBase.Name);
}

What is the most appropriate way to handle corrupt input data in a C# constructor?

I'm reading data in from a file and creating objects based on this data. The data format is not under my control and is occasionally corrupt. What is the most appropriate way of handling these errors when constructing the objects in C#?
In other programming languages I have returned a null, but that does not appear to be an option with C#.
I've managed to figure out the following options, but I would appreciate advice from more experienced C# programmers:
Option 1. Read the file inside the constructor and throw an exception when the source data is corrupt:
try
{
obj = Constructor(sourceFile);
... process object ...
}
catch (IOException ex)
{
...
}
Option 2. Create the object, then use a method to read data from the source file:
obj = Constructor();
obj.ReadData(sourceFile);
if (obj.IsValid)
{
... process object ...
}
or possibly throw exceptions on error:
obj = Constructor();
try
{
obj.Read(sourceFile);
... process object ...
}
catch
{
...
}
Option 3. Create the object using a static TryParse method:
if (ObjClass.TryParse(sourceFile, out obj))
{
... process object ...
}
and if so, should I implement option 3 internally using option 1?
public static bool TryParse(FileStream sourceFile, out ObjClass obj)
{
try
{
obj = Constructor(sourceFile);
return true;
}
catch (IOException ex)
return false;
}
I would do something along the lines of option 3):
class ObjectClass
{
protected ObjectClass(...constructor parameters your object depends on...)
{
}
public static ObjectClass CreateFromFile(FileStream sourceFile)
{
.. parse source file
if (parseOk)
{
return new ObjectClass(my, constructor, parameters);
}
return null;
}
}
And then use it like this:
ObjClass.CreateFromFile(sourcefile);
In general the constructor should take as parameters all properties which essentially define the class. Doing heavyweight calculations (like parsing a file) is best left to factory methods as it is usually not expected for the constructor to perform complex and potentially long running tasks.
Update: As mentioned in comments a better pattern is this:
public static ObjectClass CreateFromFile(FileStream sourceFile)
{
.. parse source file
if (!parseOk)
{
throw new ParseException(parseErrorDescription);
}
return new ObjectClass(my, constructor, parameters);
}
public static bool TryCreateFromFile(FileStream sourceFile, out ObjectClass obj)
{
obj = null;
.. parse source file
if (!parseOk)
{
return false;
}
obj = new ObjectClass(my, constructor, parameters);
return true;
}
I would not put anything into a constructor that might throw an exception - except for if something goes really wrong.
If your constructor has a possible return value other than a valid object, you should encapsulate it.
The safest way would probably be to create a factory method (public static function in the class that accepts a file reference and returns a new instance of the class or null). This method should first validate the file and its data and only then create a new object.
If the file data has a simple structure, you can first load it into some local variable and construct the object with this data.
Otherwise, you can still decide - inside of your factory method - if you rather want to try / catch the construction or use any of the other points mentioned above.
Both Options #1 and #3 are good choices and common in the .Net framework. It's also common to provide both for the same type. Consider Int32.TryParse and Int32.Parse. Providing both gives developers a bit more flexibility without detracting from the integrity of the type.
I would strongly advise you to avoid #2. This pattern forces both the type author and type consumer to handle instances of the type in multiple states
Constructed but not fully initialized
Initialized and valid
Initialized and invalid
This puts a burden on every consumer to deal with instances being in all different states (even if the response is to just throw). Additionally it forces a non-standard pattern on consumers. Developers have to understand your type is special and that it needs to be constructed and then initialized. It goes against the standard way objects are created in .Net.
Note for #3 though I would approach it a bit different. The exception form should be implemented in terms of the try form. This is the standard pattern when providing both options to the user. Consider the following pattern
class MyType {
struct ParsedData {
// Data from the file
}
public MyType(string filePath) : this(Parse(filePath)) {
// The Parse method will throw here if the data is invalid
}
private MyType(ParsedData data) {
// Operate on the valid data. This doesn't throw since the errors
// have been rooted out already in TryParseFile
}
public static bool TryParse(string filePath, out MyType obj) {
ParsedData data;
if (!TryParseFile(filePath, out data)) {
obj = null;
return false;
}
obj = new MyType(data);
return true;
}
private static ParsedData Parse(string filePath) {
ParsedData data;
if (!TryParseFile(filePath, out data)) {
throw new Exception(...);
}
return data;
}
private static bool TryParseFile(string filePath, out ParsedData data) {
// Parse the file and implement error detection logic here
}
}
From Microsoft Constructor Design Guidelines (MSDN),
Do throw exceptions from instance constructors if appropriate.
Constructors should throw and handle exceptions like any method. Specifically, a constructor should not catch and hide any exceptions that it cannot handle.
Factory Method is not the right way to approach this problem. See Constructors vs Factory Methods
From Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries
5.3 Constructor Design
Consider using a static factory method instead of a constructor if the
semantics of the desired operation do not map directly to the construction
of a new instance, or if following the constructor design guidelines
feels unnatural.
Do throw exceptions from instance constructors if appropriate.
.NET BCL implementations do throw exceptions from constructors
For example, the List Constructor (Int32), throws an ArgumentOutOfRangeException when the capacity argument of the list is negative.
var myList = new List<int>(-1); // throws ArgumentOutOfRangeException
Similarly, your constructor should throw an appropriate type of exception when it reads the file. For example, it could throw FileNotFoundException if the file does not exist at the specified location, etc.
More Information
Code Contracts
Throwing exceptions from constructor in .Net
Throwing ArgumentNullException in constructor?
Constructor parameter validation in C# - Best practices
All these solutions work, but as you said, C# doesn't allow to return null from a constructor. You either get an object or an exception. Since this is the C# way to go, I wouldn't choose option 3, because that merely mimics that other language you're talking about.
Lots of people [edit] among which is Martin, as I read in his answer :) [/edit] think it is good to keep your constructor clean and small. I'm not so sure about that. If your object is of no use without that data, you could read in the data in the constructor too. If you want to construct the object, set some options, and then read the data (especially with the possility to try again if the read fails), a separate method would be fine as well. So option 2 is a good possibility too. Even better maybe, depending mainly on taste.
So as long as you don't choose 3, choose the one you're the most comfortable with. :)

Categories