Pass object (List<string>) as part of Exception - c#

I am constructing a list of strings and then want to throw an exception and let the UI handle the list and create the error message for the user.
Is there a way to do that?

Exceptions contains Data property (which is a dictionary). It can be used to pass additional information:
try
{
// throw new Exception
}
catch(Exception e)
{
// whatever
e.Data["SomeData"] = new List<string>();
}

You can use the Exception.Data property to pass arbitrary data but a better (cleaner) solution would be to create your own custom exception class derived from Exception and add whatever properties you need to it.
Sample code:
public class MyException: Exception
{
public List<String> MyStrings { get; private set; }
public MyException(List<String> myStrings)
{
this.MyStrings = myStrings;
}
}

Related

how to use object class instance recived as command parameters in WPF

I am passing command parameters to a command. and receiving it like this
public void SelectTestCase(object Dev)
{
try
{
_navigationStore.CurrentViewModel = new TestCaseViewModel(_navigationStore);
}
catch (Exception e)
{
}
}
in this Object Dev will be carying data related to Device. but if i do dev.DeviceName this is giving error because dev object is recieving data on runtime.
how can i use this Dev object and get data on runtime
You have the parameter specifically as a generic "object" rather than the specific class type. You need to type-cast it. Ex:
public void SelectTestCase( object Dev )
{
if( Dev is myDeviceTypeClass )
{
var tmp = (myDeviceClass)Dev;
// Now you can use as needed
MessageBox.Show( tmp.DeviceName );
}
// if you have different POSSIBLE device classes passed in,
// just test for those too.
}
Assuming that Dev is actually a fixed type then you could try to define a Device class matching the properties.
public void SelectTestCase(Device Dev)
and something like
public class Device
{
public string DeviceName {get;set;}
// other properties
}

Extend SqlException and add a property to it

I'm trying to extend System.Data.SqlClient.SqlException and add a property to it. So that, on every SqlCommand execution, if an exception is thrown, I can capture it, add the SQL that was executed, and re-throw it.
I have done extensions before, but only with methods. With properties I can't manage it to work.
public static class SqlExceptionExtention{
public static string query { get; set; }
}
I have tried all combinations of adding and removing the static flag, and nothing works. Of course the property can't be static, it must be specific to each object.
There's no such thing as extension properties, only extension methods.
If you want to add data then you could use the Data property to populate the dictionary:
try
{
// Do something
}
catch(SqlException e)
{
e.Data.Add("Foo", "Bar");
throw;
}

Using variable outside Try-Catch

I need to use the value of a variable initialized inside a try block. I have this basic code
Customer customer = null;
try
{
customer = new Customer(....);
}
catch (Exception){}
string customerCode = customer.Code;
If there is no exception, the customer is perfecly usable, but if there is an exception, customer is not initialized, it returns null
I have checked that customer ALLWAYS initializes correctly INSIDE the block. INSIDE It is perfectly usable even in case of exception. But I need it for later use.
Any way to ALLWAYS keep the customer? :)
EDIT:
As you supposed, this was pseudocode. As I can read, it looks like to use exceptions in constructors is a BAD idea. This is part of my REAL code for my constructor.
public class DirectDebitRemmitanceReject
{
int numberOfTransactions;
decimal controlSum;
List<DirectDebitTransactionReject> directDebitTransactionRejects;
public DirectDebitRemmitanceReject(
int numberOfTransactions,
decimal controlSum,
List<DirectDebitTransactionReject> directDebitTransactionRejects)
{
this.numberOfTransactions = numberOfTransactions;
this.controlSum = controlSum;
this.directDebitTransactionRejects = directDebitTransactionRejects;
if (TheProvidedNumberOfTransactionsIsWrong()) ChangeNumberOfTransactionsAndRiseException();
if (TheProvidedControlSumIsWrong()) ChangeControlSumAndRiseException();
}
private bool TheProvidedNumberOfTransactionsIsWrong()
{
return (numberOfTransactions != directDebitTransactionRejects.Count)
}
private bool TheProvidedControlSumIsWrong()
{
return (controlSum !=directDebitTransactionRejects.Select(ddRemmitanceReject => ddRemmitanceReject.Amount).Sum();)
}
private void ChangeNumberOfTransactionsAndRiseException()
{
......
......
throw new ArgumentException(exceptionMessage, "numberOfTransactions")
private void ChangeControlSumAndRiseException()
{
......
......
throw new ArgumentException(exceptionMessage, "controlSum")
}
}
In the methods 'TheProvided...' I check if the arguments are congruent with the sum of values in the list. If not, I update them and inform by raising an ArgumentException
The fact is that I wanted the constructor ALLWAYS returns a valid (congruent) DirectDebitRemmitanceReject, but desired the same constructor to rise the exception if provided wrong numberOfTransactions or controlSum. NumberOfTransactions and controlSum should not be modified later, only readed.
In my tests, this works well
[TestMethod]
[ExpectedException(typeof(System.ArgumentException))]
public void IfTheProvidedControlSumInARemmitanceRejectIsWorgAnExceptionIsThrown()
{
try
{
DirectDebitRemmitanceReject directDebitRemmitanceReject = new DirectDebitRemmitanceReject(
originalDirectDebitRemmitance1MessageID,
2,
100,
directDebitTransactionRejectsList1);
}
catch (System.ArgumentException e)
{
Assert.AreEqual("controlSum", e.ParamName);
Assert.AreEqual("The Control Sum is wrong. Provided: 100. Expected: 150. Initialized with expected value", e.GetMessageWithoutParamName());
throw;
}
}
[TestMethod]
public void IfTheProvidedControlSumInARemmitanceRejectIsWorgItIsCorrected()
{
try
{
DirectDebitRemmitanceReject directDebitRemmitanceReject = new DirectDebitRemmitanceReject(
originalDirectDebitRemmitance1MessageID,
2,
100,
directDebitTransactionRejectsList1);
Assert.AreEqual(150, directDebitRemmitanceReject.ControlSum);
}
catch (ArgumentException) { }
}
But i can,t Assert the directDebitRemmitanceReject.ControlSum outside the 'try' block
So... do I try another aproach (remove the exception from inside the constructor) or is there another workaround?
Thanks! :)
(Sorry for the EXTENSIVE edit) :(
Your example is a perfect illustration of why writing
catch (Exception){}
is a very bad practice.
When you catch an exception, you are supposed to do something about it. If you do not know what to do with an exception in a particular method of your code, don't catch the exception in that method.
If you always need a customer, even when its retrieval causes an exception, add some code to the catch block to set customer variable to some default object:
try {
...
} catch (Exception) {
customer = Customer.Unknown;
}
This assumes that Customer has a property Unknown of type Customer with some default behavior.
Comment: Needed to warn the upper level of my code. Just, when I create an instance, create it, but warn the arguments where wrong. Could you recommend me some better approach?
Make a factory for validating users while creating them:
class CustomerCreationResult {
public Customer Customer() { get; set; }
public CustomerCreationError Error() { get; set; }
}
class CustomerFactory {
public CustomerCreationResult CreateCustomer(String name, int age) { ... }
}
Now you can create your customers as follows:
var r = myCustomerFactory.CreateCustomer(name, age);
if (r.getError() != null) {
... // Present the error
}
Customer customer = r.Customer;
...
If customer always initializes correctly, then why do you have it in the try block?
If you want to persist it when an exception occurs, either move the initialization of customer outside of the try block or use try/catch for smaller chunks of code.
for example:
Customer customer = null;
try
{
//in this block do the stuff that is unlikely to cause exceptions
customer = new Customer(...);
try
{
//stuff that is likely to cause exceptions
}
catch(Exception e)
{
//handle likely errors
}
catch (Exception e)
{
//handle the unusual errors
}
I think 'dasblinkenlight's answer is very good, but for the simplest purpose an if would be enough:
string customerCode = "";
if (customer!=null)
{
customerCode = customer.Code;
}
And you really should check the exception...

If I throw an exception in a getter of a property, can I obtain the name of the property in a catch block?

If I throw an exception from a getter of a property, is it possible to obtain the name of
the property in the catch block where I have called that property -like using reflection or
reading the stack trace?
For instance:
class Animal
{
private string _name;
public string Name {
get { throw new Exception(); }
set { _name = value; }
}
}
And in another place, I call the Name property's getter and I want to obtain the property name in the catch block:
Animal cat = new Animal();
try{
string catName = cat.Name;
}
catch (Exception e)
{
string propertyName = //Here I should be able to reach "Name"
}
it will show in your stack trace as exception in get_Name() method. you can probably parse it to get the Property Name
There are two options, non of which are great:
Parse the get_Name() method from the Exception.StackTrace property, as Ashley and Mongus describe. This will fail when the getter gets inlined (which is not unlikely to happen), because inlined methods calls will (obviously) not show up in the stacktrace.
Throw a special exception that contains that property name:
public string PropertyName
{
get { throw new PropertyException("PropertyName", "Ex message.");
}
This however isn't great either, since you should explicitly throw this type of exception. So failures from deeper down the callstack must be wrapped in that PropertyException.
You could parse e.StackTrace using a Regex :
try
{
int x = this.Ong;
}
catch ( Exception ex )
{
Console.WriteLine ( Regex.Match ( ex.StackTrace, #"get_(?<prop>.*)\(\)" ).Groups["prop"].Value );
}
Note You should put more error checking on the Regex above as Groups["prop"] may be null if the exception isn't raised from a property.
If you're considering something like this you most likely would be far better off implementing something like the INotifyPropertyChanged and stick this as part of your getter instead of only caring about the setter like normal usage.
How to: Implement the INotifyPropertyChanged Interface
Exception.TargetSite
Since C# 5, you can use CallerMemberNameAttribute.
public class SomeCustomException : Exception
{
public string PropertyName { get; }
public SomeCustomException(string propertyName)
: base($"Property {propertyName} was null)
{
this.PropertyName = propertyName;
}
}
public class Animal
{
public string Name
{
get { Throw(); }
}
private static void Throw([CallerMemberName] string propertyName = null)
{
// propertyName will be 'Name'
throw new CustomException(propertyName);
}
}
I could have put [CallerMemberName] directly on the constructor for SomeCustomException, but that seems unnecessarily ugly: the exception doens't need to know that it will be called from the property getter, hence the separate static Throw method.

How can i add property to a class dynamically

I want to create an error class. And it has some static properties. For example : Message, InnerException, Stacktrace, Source. But I want to add some dynamic properties.
If exception is a FileNotFoundException, I want to add FileName property.
Or if it is a SqlException, I want to add LineNumber property. And I can't inherit that class from Exception because, I return that class from a web service. How can I do that?
C# is a statically typed language. This means you generally cannot dynamically add properties to classes at run-time without some really funky IL injection (which you definitely want to avoid).
In your case it seems that you need to understand exceptions a bit better - we usually throw a specific type of exception to indicate the cause of an exceptional problem. For example, if you are looking for a file and it's not there you would throw a FileNotFoundException or if there is some application-specific problem you could create your own exception class and throw that exception.
Keep in mind that exceptions should be exceptional.
Instead of trying to do something C# currently doesn't handle very well, I suggest you take a somewhat different approach.
Why don't you add those extra properties as data in a dictionary? Your class could expose an interface to get a number of "properties" (in the general sense of the word), i.e. the keys and your calling code could then examine these and use them to look up values as necessary.
you can create type dynamically using new features in C# like anonymous types
I am not sure if you are trying to do some thing similar, but can achieve the requirement as follows
public interface IError { }
public class ErrorTypeA : IError
{ public string Name; }
public class ErrorTypeB : IError
{
public string Name;
public int line;
}
public void CreateErrorObject()
{
IError error;
if (FileNotFoundException) // put your check here
{
error = new ErrorTypeA
{
Name = ""
};
}
elseif (InValidOpertionException) // put your check here
{
error = new ErrorTypeB
{
Name = "",
line = 1
};
}
}
Hope this helps
My take on this would be to use a dictionary where you can store all extra data.
public class Logging
{
private Dictionary<string, string> _ExtraInfo = new Dictionary<string, string>();
public Dictionary<string, string> ExtraInfo {
get { return _ExtraInfo; }
set { _ExtraInfo = value; }
}
}
To use:
Logging MyLogger = new Logging();
MyLogger.ExtraInfo.Add("Filename", thefilename);
MyLogger.ExtraInfo.Add("ClientTime", now);
And so on.
It's very unclear what you're trying to achieve. Reconsider your design in favor of non-static classes and use inheritance.
And you do remember that there are lots of ready-made exception classes in the .NET BCL, right?
Create a new exception type, derived from Exception. Throw this exception, and set the InnerException property to the exception that caused all the ruckus.
You can check for the type of the inner exception and display data accordingly.
If possible, you could of course also just throw the original excpetion to have the caller handling it.

Categories