I have this piece of code that consumes too much vertical space and it's too verbose.
if (property == null)
{
throw new XamlParseException($"Cannot find a property named \"{Name}\" in the type {underlyingType}");
}
Isn't there an equivalent method, but more legible and compact?
Something in the shape of
ThrowIfNull<XamlParseException>(message)
You can always create an extension method:
public static class ClassContracts {
public static void ThrowIfNull(this Object item)
{
if(item == null) throw new XamlParseException("Your message here", null);
}
}
This way you use up less space which is what you were talking about, and you can use the code over and over whenever you need it. I have a library of these for testing for nulls etc. I like doing it this way over Code Contracts, because that requires the binary rewriter and depending on your environment, your build system (if you have one) may not support doing that. Ultimately, Code Contracts do more than just this, but in a pinch this offers a quick and concise way of checking for nulls and other conditions easily in code as you can create other ones like:
public static void CheckForCondition <T>(this T item, Predicate<T> p, Func<Your_Exception_Type> createException)
{
if(p(item)){throw createException();}
}
With this base method, you can then create other ones and create overloads, etc. have the predicate, or the exception method already created.
public static void CheckForNullCondition<T>(this T item)
{
item.CheckForCondition(x => x == null,
() => new Exception("Item is null"));
}
Extension Methods
I have no knowledge of such method but you can either create it by yourself or just move message to the resources file/internal constant (of course if the space taken by it is the case).
Extension approach is also viable option if it is acceptable for you (I mean having such extension for PropertyInfo or any other type).
Related
I have this method in C# that looks like I should really refactor it . Should I use a design pattern ? Too much repetition is what I see NOW and especially as MORE conditional if statements get added
Change to a method?
public void CreateOrUpdateReportDefinition(ReportGroupSubReport reportGroupSubReport, bool isNew, int report)
{
if (report == 1)
{
var entity = _envyUnitOfWork.ReportDefinitions.GetById(reportGroupSubReport.Id) ?? new ReportDefinition();
if (isNew)
entity.SetNew();
_envyUnitOfWork.ReportDefinitions.InsertOrUpdate(entity, true);
}
else if (report == 2)
{
var entity = _envyUnitOfWork.TraxReports.GetById(reportGroupSubReport.Id) ?? new TraxReport();
if (isNew)
entity.SetNew();
_envyUnitOfWork.TraxReports.InsertOrUpdate(entity, true);
}
Mapper.Map(reportGroupSubReport, entity);
_envyUnitOfWork.Commit();
}
So what I would do is to put every single conditional behavior into separate method. To avoid repetition you could use the template method pattern. You should also declare your report variable before all if statements so that it would be accessible for the Mapper.Map().
Edit:
Ok, so assuming that both _envyUnitOfWork.TraxReports and _envyUnitOfWork.ReportDefinitions share some common generic interface (which I named Repository in code) defining GetById and InsertOrUpdate methods, you do not need to use any design patterns - simple generic method will do the job. Here is example of the code:
private void createOrUpdateReportDefinition<Report>(ReportGroupSubReport reportGroupSubReport, bool isNew, Repository<Report> repository/*, Action<Report> insertOrUpdate*/) where Report : new()
{
var entity = repository.GetById(reportGroupSubReport.Id) ?? new Report();
if (isNew)
entity.SetNew();
repository.InsertOrUpdate(entity, true);//insertOrUpdate(entity, true);
Mapper.Map(reportGroupSubReport, entity);
_envyUnitOfWork.Commit();
}
public void CreateOrUpdateReportDefinition(ReportGroupSubReport reportGroupSubReport, bool isNew, int report)
{
if (report == 1)
{
createOrUpdateReportDefinition(reportGroupSubReport, isNew, _envyUnitOfWork.ReportDefinitions/*, _envyUnitOfWork.ReportDefinitions.InsertOrUpdate*/);
}
else if (report == 2)
{
createOrUpdateReportDefinition(reportGroupSubReport, isNew, _envyUnitOfWork.TraxReports/*, _envyUnitOfWork.TraxReports.InsertOrUpdate*/);
}
}
Please take under consideration this code is dealing only with one issue in your code which was the code duplication, there are still few things you could improve like removing int report parameter from the method either by dividing it into few methods or at least by replacing it with some enum with meaningful name. I would also suggest the same (dividing the methods) for the bool isNew parameter, since using it means your function doesn't do one thing only which is against single responsibility principle from SOLID - you can read more about it here.
The following refactoring pattern might give you some clues as to how you could manage the proliferating conditional problem: https://sourcemaking.com/refactoring/replace-conditional-with-polymorphism
Edit: The easiest way to do this would be defining an Interface that both TraxReports and ReportDefinition implement that has a InsertOrUpdate method.
private static void AssertNotNullAndAreEqual<T, TK>(T expected, TK actual)
{
Assert.IsNotNull(expected);
Assert.AreEqual(expected, actual);
}
I can call it using:
AssertNotNullAndAreEqual(expected.FirstName, actual.FirstName);
Is there any simple way that I can know the "FirstName" text of the expected object from within this method?
I'd need it for logging purposes and giving proper error messages from within this method.
The C# caller information doesn't help here.
I would rethink that approach, because this might bite back at some point - but if you're really keen on getting some degree of automation, you could try this:
private static void AssertNotNullAndAreEqual<T, TK>(Expression<Func<T>> expected,
Expression<Func<TK>> actual)
{
var memberExpression = expected.Body as MemberExpression;
if (memberExpression != null)
{
var expectedMemberName = memberExpression.Member.Name;
var expectedVal = expected.Compile()();
var actualVal = actual.Compile()();
Assert.IsNotNull(expectedVal);
Assert.AreEqual(expectedVal, actualVal);
//...
}
}
Now your calls would have to look as follows:
AssertNotNullAndAreEqual(() => expected.FirstName, () => actual.FirstName);
Few more caveat
a lot of stuff will not be checked until compile time (luckily type-safety is preserved). It's easy to write calls that will compile correctly, but fail at runtime.
as this is written, it won't work with variables - but if you decide to go this way, it would be pretty easy to write.
Please use at your own discretion :)
If you're using ToString() for another purpose (which I assume you are), you can define an interface and use it as a type constraint on AssertNotNullAndAreEqual(...), or alternately check to see if the objects passed to AssertNotNullAndAreEqual(...) have the interface.
You define an interface, say IDebugString, which has a ToDebugString() method, then you call that to retrieve the info to log.
I'm writing a program in C# (3.5 at the moment, but likely to be adaptable to other versions as the need arises) that uses a simple plugin architecture to control input and output. Each plugin is a DLL that is loaded when the user chooses the plugins to use.
Since the actual plugin class isn't known until run time, I'm using reflection in a wrapper class to call methods and access properties of the plugins.
Up until now, I've been using the following to call methods on a plugin:
public object Method(string methodName, params object[] arguments) {
// Assumed variables/methods/exceptions:
// Dictionary<string, MethodInfo> Methods: a cache of MethodInfo's
// of previously called methods.
// NoSuchMethodException: thrown if an unknown/unreachable method is
// requested. The message member contains the invalid method name
// void LoadMethod(string methodName, params object[] arguments): responsible
// for retrieving the MethodInfo's, or throw a NoSuchMethodException
// object Plugin: an instance of the dynamically loaded class.
if (!Methods.ContainsKey(methodName)) {
LoadMethod(methodName, arguments);
}
if (arguments != null && arguments.Length == 0) {
arguments = null;
}
return Methods[methodName].Invoke(Plugin, arguments);
}
Which is used like:
string[] headers = (string[]) Plugin.Method("GetHeaders", dbName, tableName);
This works nicely, as long as the caller correctly casts the return value to the expected
type. Plugins must implement certain interfaces, so the caller should know this type.
After doing some further work with reflection however, the following alternate form occurred to me:
public T Method<T>(string methodName, params object[] arguments) {
if (!Methods.ContainsKey(methodName)) {
LoadMethod(methodName, arguments);
}
if (Methods[methodName].ReturnType != typeof(T)) {
// Could also move this into LoadMethod to keep all the throwing in one place
throw new NoSuchMethodException(methodName);
}
if (arguments != null && arguments.Length == 0) {
arguments = null;
}
return (T) Methods[methodName].Invoke(Plugin, arguments);
}
This one is used like:
string[] headers = Plugin.Method<string[]>("GetHeaders", dbName, tableName);
This version essentially moves the casting into the Method method. The caller obviously still needs to know the expected return type, but that was always going to be the case. It doesn't work for void methods, but I can include a version of Method for that:
public void Method(string methodName, params object[] arguments) {
// Good for void methods, or when you're going to throw away the return
// value anyway.
if (!Methods.ContainsKey(methodName)) {
LoadMethod(methodName, arguments);
}
if (arguments != null && arguments.Length == 0) {
arguments = null;
}
Methods[methodName].Invoke(Plugin, arguments);
}
My question is - is one of these intrinsically better than the other (for a given value of 'better')? For instance, is one notably faster? Easier to understand? More supported?
I personally like the look of the latter, although I am a bit worried that my return type testing (Methods[methodName].ReturnType != typeof(T)) might be too simplistic. Interestingly, it was originally !(Methods[methodName].ReturnType is T), but that always seemed to fail.
The closest existing question to this I could find was Generic method to type casting, and some of the answers suggested that the latter method is more expensive than the former, but there's not much in the way of detail there (the question there is more towards implementation of the method rather than which is better).
Clarification: This is a hand-rolled, very limited plugin system, not using IPlugin. I'm more interested in the question of whether generic methods are inherently better/worse than expecting the caller to cast in this situation.
As to your question I think you should provide both. Simply have the generic version invoke the non-generic version. You get the best of both worlds. Regarding performance, consider how small the time it takes to cast an object is in comparison to dynamically invoking a method and building up and object array. It really is not worth taking performance into consideration here. I for one prefer the generic approach from a stylistic perspective but also consider that you could apply type constraints should the need arise.
public T Method<T>(string methodName, params object[] arguments)
{
return (T)Method(methodName, arguments);
}
Side Bar
I'm thinking that your implementation should be casting to the expected interface if I understand your design. You really should not be using reflection if you know what methods the plugins should support.
var plugin = (IPlugin)Activator.CreateInstance(pluginType);
var headers = plugin.GetHeaders(dbName, tableName);
You could try something a bit different and require the plugin to implement an interface that allows them to register custom runtime behavior.
public interface IPlugin
{
void Load(IAppContext context);
void Unload();
}
Your loading method could look like this.
void LoadPlugins(Assembly a)
{
var plugins =
a.GetTypes()
.Where(t => typeof(IPlugin).IsAssignableFrom(t))
.Select(t => (IPlugin)Activator.CreateInstance(t))
.ToList();
Plugins.AddRange(plugins);
foreach (var p in plugins)
{
p.Load(Context);
}
}
I have some logging logic I want to call before and after several methods. Each method accepts different number/type of parameters. I'm trying to set it up so I don't have to duplicate the logging logic when I call each method. I've been able to reduce the amount of duplication by creating some delegates. I've created a delegate for each number/type of parms used and I have a method that accepts each delegate and does the logging. However, I still have around 6 different delegates and so the logic is duplicated for those six.
I think there is away to modify this so regardless of the number of parms, I have one method that does the logging and calls the method. But I haven't been able to figure it out.
Below is an example of one of the delegates and the logic I'm trying not to duplicate.
public delegate void LineOfBusinessHandler(DateTime runDate, LineOfBusinessCode lineOfBusinessCode);
public void Run(DateTime runDate, ProcessCode process, LineOfBusinessCode lineOfBusinessCode, LineOfBusinessHandler del)
{
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Started.ToString(), null, runDate);
try
{
del(runDate, lineOfBusinessCode);
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Finished.ToString(), null, runDate);
}
catch (Exception e)
{
int errorId = SystemManager.LogError(e, process.ToString());
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Errored.ToString(), errorId, runDate);
}
}
I realize this maybe beyond the scope and/or the capabilities of what you're looking for. But if you have a generic logging logic that you want to reuse over different method calls, without losing typesafety (i.e. NOT passing your arguments around in object[]) the way to go is interception. You need a framework (I don't recommend writing your own at first!) that can provide AOP, Dependency Injection or something similiar. Those things can usually deal with interception.
For example I have a logging interceptor I use with Ninject:
public void Intercept(IInvocation invocation)
{
var logger = LoggerFactory.GetLogger(invocation.Request.Method.DeclaringType);
var debug = !invocation.Request.Method.IsSpecialName && logger.IsDebugEnabled;
if (debug)
logger.Debug(invocation.Request.Method.Name);
try
{
invocation.Proceed();
if (debug)
logger.Debug(invocation.Request.Method.Name + " FINISH");
}
catch (Exception)
{
logger.Error(invocation.Request.Method.Name + " ERROR");
throw;
}
}
Then I create my objects by getting them with Ninject (if you don't know about it, check out some tutorials), while adding some Interception to them, for example: Kernel.Bind<MyTypeToLog>().ToSelf().Intercept().With<LoggingInterceptor>(); where LoggingInterceptor implements IInterceptor with the method shown above...
Just say if you need more in details help!
EDIT: just realized that my example doesn't show this, but you can access the arguments (as an object collection though) of the invocation too!!
It depends on what is common among the different versions, but assuming runDate and process are common you could do something like this:
public void Run(DateTime runDate, ProcessCode process, LineOfBusinessCode lineOfBusinessCode, LineOfBusinessHandler del)
{
this.DoRun(runDate, process, (d, p) => del(d, p, lineOfBusinessCode));
}
public void DoRun(DateTime runDate, ProcessCode process, Action<DateTime, ProcessCode> action)
{
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Started.ToString(), null, runDate);
try
{
action(runDate, process);
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Finished.ToString(), null, runDate);
}
catch (Exception e)
{
int errorId = SystemManager.LogError(e, process.ToString());
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Errored.ToString(), errorId, runDate);
}
}
You can even generalize so you don't have do define custom delegates as this:
public void Run<T1>(DateTime runDate, ProcessCode process, T1 param1, Action<DateTime, ProcessCode, T1> del)
{
this.DoRun(runDate, process, (d, p) => del(d, p, param1));
}
public void Run<T1, T2>(DateTime runDate, ProcessCode process, T1 param1, T2 param2, Action<DateTime, ProcessCode, T1, T2> del)
{
this.DoRun(runDate, process, (d, p) => del(d, p, param1, param2));
}
The C# language doesn't have any syntax for metaprogramming. You'll have to use reflection. You certainly can reflect against an arbitrary method/delegate to determine the parameter types, then build a method that logs parameters and calls the original method, compile this new wrapper method, and return a delegate with the same call signature as the original.
You can do this at runtime (return a delegate) or build a new assembly with all the wrapper functions, that can then be referenced by your code and used normally.
You should look at the code-weaving tools used for Aspect-Oriented-Programming. Some of them already do this.
Unlike using a params array, this gives you a wrapper with the same signature (or delegate type) as the original method, so it is type safe and Intellisense works (as much as for any other delegate).
If I understand your question correctly it sounds like you could use the C# params keyword. See this for a reference on how to use it: http://msdn.microsoft.com/en-us/library/w5zay9db.aspx
One of the requirements when using params is that it has to be placed last in the signature of the function. Then, inside of the function you can enumerate and iterate over the variable parameters list as if it were an array.
EDIT
To expand on a comment posted by #Ben Voigt, another limitation of using the params keyword is that it requires the variable parameter list to be of the same type. This however can be mitigated in your case since all you care about is logging. In this case presumably you would be invoking the ToString() method on the objects you need to log so you could make the variable parameters list of type object.
In case calling the ToString() is not enough and you have different types of objects you could make all these objects implement a common interface. Let's call it ILoggableObject which exposes a method to provide the logging output. That's if you have the ability to change those objects.
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. :)