What is the elegant solution to access nested property values?
Example:
In some cases it could look as follows:
public void someFunction()
{
this.Device.ResponseHandler.Process(this.Device.TcpClient.responseMessage, this.Device.TcpClient.responseType)
}
My solution was to copy objects, just to shorten the names afterwards.
public void someFuntion()
{
// Just for shorten the access name afterwards
ResponseHandler responseHandler = this.Device.RepsonseHandler;
TcpClient tcpClient = this.Device.TcpClient;
responseHandler.Process(tcpClient.responseMessage, tcpClient.responseType);
}
It is mostly opinion based, but there are generally two ways:
The one you are using.
List every argument in new line:
public void someFunction()
{
this.Device.ResponseHandler.Process(
this.Device.TcpClient.responseMessage,
this.Device.TcpClient.responseType
);
}
IMO both are equally readable and in second approach you don't need another variables :)
You could add a usings at the top if you don't like long names:
using ResponseHandler = this.Device.ResponseHandler;
using TcpClient = this.Device.TcpClient;
public void someFunction()
{
ResponseHandler.Process(TcpClient.responseMessage, TcpClient.responseType);
}
Related
I have a class that has a field that is being assigned a value from multiple methods.
public class Shape
{
private Point2D m_location;
public void Move()
{
m_location = ...
}
public void Rotate()
{
m_location = ...
}
public void Flip()
{
m_location = ...
}
}
I am getting a warning from NDepend that says:
Don't assign a field from many methods
https://www.ndepend.com/default-rules/Q_Don't_assign_a_field_from_many_methods.html
I am thinking of solving this problem by creating a separate method to assign the value of the field and calling this method from the other methods that currently assign a value to the field.
Here is an example of the code:
private void SetLocation(Point2D point)
{
m_location = location;
}
I want to know if this is a valid way to solve the problem and if it will just hide the code-smell that NDepend detected or actually fix the issue.
Is this a valid way to solve this problem?
No. As you suspect, this is a code smell. What NDepend is complaining about is mutable references; you have code where:
var s = new SomeObject(someInitialization);
var r = s.SomeResult();
// you now have no idea what s contains or if it is even usable any more.
The solution to this is to make SomeObject immutable and return new references instead of changing internals:
public SomeObject Something()
{
return new SomeObject(SomethingDifferentDependingOn(this.something));
}
Now instead of your first example you have:
var s = new SomeObject(someInitialization);
var r = s.Something().Result;
// s is guaranteed to be unchanged.
Yes some times you will need mutable references. In those cases; document them and explain why they have to be mutable. Then you can override NDepend rules on a case-by-case basis to prevent it showing a warning. If you have a code smell, warn people. Do not try to hide it.
The example after your edit is quite different, but the general principle still holds. If you have only a few internal fields that all change in method calls you can still return immutable references, e.g.:
public Shape Move()
{
return new Shape(m_location ...);
}
If you have many internal fields that don't all change, or you need to do something like share private fields you can't easily have immutable reference, but you can still avoid the warning by using accessors:
public Location
{
get { return m_location; }
private set { m_location = value; }
}
Then use Shape.Location exclusively in your internal methods.
I created a class where the main task is get data from the DB and mapping it to some object. The problem is the same class needs to map different datareader to different object. So, what I tried to do is to get out the mapping method using delegates.
Here is part of my code. See the important rows in bold.
public class GetDetails<T>
{
**public delegate void DelegateMapping(T position, IDataReader reader);**
**public DelegateMapping mappingMethod;**
public T Get(T instance)
{
//Get IDs and Add to list
_db.ExecuteReader(storedProcedure.ToString(), CommandType.StoredProcedure, reader =>
{
while ( reader.Read() )
{
**mappingMethod(instance, reader);**
}
}, parameterList.ToArray());
return instance;
}
}
And this is the class which is calling and using the "GetDetails" class
public class PositionDB : DbBase
{
public Position GetPositionDetails(string IDs)
{
GetDetails<Position> getIDs = new GetDetails<Position>(base.db);
getIDs.storedProcedure = StoredProcedure.NET_ADM_GetPositionDetails;
//Set the Delegated Method
**getIDs.mappingMethod = MappingPositionDetails;**
//Set Parameters
getIDs.parameterList.AddInParam("PositionIds", DbType.String, IDs);
//Return the PositionId Collection
return getIDs.Get(new Position());
}
**private void MappingPositionDetails(Position position, IDataReader reader)
{
position.Id = reader["CompPositionId"];
position.Description = reader["Description"];
position.ExpirationDate = reader["ExpirationDate"];
position.Title = reader["Title"];
}**
}
The code is working OK.
The questios are:
Did I use delegate correctly?
This kind of solution can cause problems in the future (performance)?
There is another better solution?
Thank you very much
Sebastian
To specifically answer your questions:
Yes, you did use delegates correctly
Yes, it can cause problems due to concurrency issues while multithreading
I think so, I detailed one possible solution below
I would propose three changes:
Move the delegate call into the method (concurrency issues, one thread could change the mapping delegate while another thread tries to access it, now trying to map a reader to completely different object than provided)
Use the already present generic Action/Func delegates, no need to define your own.
Use lambda expressions to define the mapping, no need for extra methods
Notice: 2 and 3 will need at least .net 3.5.
Employing these two proposals, your code would look like this:
public class GetDetails<T>
{
public T Get (T instance, Action<T, IDataReader> mappingMethod)
{
//Get IDs and Add to list
_db.ExecuteReader(storedProcedure.ToString(), CommandType.StoredProcedure, reader =>
{
while ( reader.Read() )
{
mappingMethod(instance, reader);
}
}, parameterList.ToArray());
return instance;
}
}
Now you can use this method in a multi-threaded environment as well.
Edit
just realized it's just part of the code. I corrected my proposal to take this into account.
Yes (There's some improvements you could make, see 3)
Not performance wise, maybe some issues in discoverability.
I would use polymorphism to eliminate the delegate completely for discoerability. Perhaps using an abstract method/class. Also depending on which .NET version you're developing for you can use lambdas and simpler types.
public Action<Position, IDataReader> Mapping { get; set; }
Then
getIDs.Mapping = (position, reader) =>
{
position.Id = reader["CompPositionId"];
position.Description = reader["Description"];
position.ExpirationDate = reader["ExpirationDate"];
position.Title = reader["Title"];
};
I am creating a network chat client in C# as a side project. In addition to simple text messages, I also have slash-prefixed commands that can be entered into the input TextBox. I used a modular approach by creating an enum that contains all the various commands, and then decorating those commands with attributes.
The attributes specify what slash-prefixed command can be entered to trigger the command, as well as any aliases to the primary command identifier and the command's usage.
Example:
public enum CommandType : byte
{
[PrimaryIdentifier("file"),
AdditionalIdentifier("f"),
CommandUsage("[<recipient>] [<filelocation>]")]
FileTransferInitiation,
[PrimaryIdentifier("accept"),
AdditionalIdentifier("a")]
AcceptFileTransfer,
// ...
}
My problem arises when I try to allow multiple aliases to the primary command. I have attempted this two ways: by allowing duplicates of the AdditionalIdentifier attribute, or by making the constructor argument in AdditionalIdentifier a params string[].
With the former, I implemented it by decorating the attribute class with AttributeUsage and setting AllowMultiple to true. While this does indeed achieve what I'm looking for, I'm feeling like it could get really noisy really fast to have several lines of aliases, in addition to the other attributes.
The latter also works, however, it generates the compiler warning CS3016, and says that that approach is not CLS-compliant. Obviously, this doesn't necessarily stop me from still using it, but I've learned to always treat warnings as errors.
My actual question is should I ignore my objections with duplicates and just go ahead and use them, or is there some other solution that could be used?
Thank you.
You could also use "params string[] aliases" in the constructor to allow a variable argument list:
[AttributeUsage(AttributeTargets.Method)]
class TestAttribute : Attribute
{
public TestAttribute(params string[] aliases)
{
allowedAliases = aliases;
}
public string[] allowedAliases { get; set; }
}
This would allow you to do:
[Test("test1", "test2", "test3")]
static void Main(string[] args)
Personally I would go with the AllowMultiple approach: I don't think the "noise" is going to be that much of a problem unless you really have truckloads of identifiers for each command. But if you don't like that and want to stay CLS-compliant, one other solution would be to provide overloaded constructors for AdditionalIdentifierAttribute:
public AdditionalIdentifierAttribute(string id) { ... }
public AdditionalIdentifierAttribute(string id1, string id2) { ... }
public AdditionalIdentifierAttribute(string id1, string id2, string id3) { ... }
The downside is that this does limit you to a predetermined number of identifiers.
That said, CLS compliance is really only a major consideration if you are building a library that others are likely to use (and specifically from other languages). If this type or the library is internal to your application, then it's reasonable to ignore CLS compliance warnings.
EDIT: Thinking further about this, you have quite a lot of attributes on those enums. You might want to consider creating an abstract Command class instead, and exposing the identifiers, usage, etc. as properties of that class; then derive concrete types of Command which return the appropriate values from those properties. This potentially also allows you to move the handling logic into those Command objects rather than switching on the enum value.
Why not have a single attribute with multiple properties? Have the property for the alias take a comma-separated list. This is the approach they take in MVC for things like the AuthorizeAttribute for Roles. Internally, the property parses the string into an array for ease of use in the attribute class, but it allows you an easy way to set up your configuration.
public class IdentifierAttribute
{
public string Name { get; set; }
public string Usage { get; set; }
private string[] aliasArray;
private string aliases;
public string Aliases
{
get { return this.aliases; }
set
{
this.aliases = value;
this.aliasArray = value.Split(',').Trim();
}
}
}
Then use it like:
public enum CommandType : byte
{
[Identifer( Name = "file", Aliases = "f", Usage = "..." )]
FileTransferType,
...
}
Yet another approach would be to have the attribute take an array of strings as a constructor parameter - that way, you get the compiler to parse the array for you (at the expense of a little more goop when applying the attribute) thus:
[Identifiers(new string[] {"Bill", "Ben", "Ted"})]
A quick 'n dirty example of implementing & using such a technique looks like this:
using System;
using System.Collections.ObjectModel;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
SomeClass.TellMeAboutYourself();
}
}
public class Identifiers : Attribute
{
private string[] names;
public Identifiers(string[] someNames)
{
names = someNames;
}
public ReadOnlyCollection<string> Names { get { return new ReadOnlyCollection<string>(names); } }
}
[Identifiers(new string[] {"Bill", "Ben", "Ted"})]
static class SomeClass
{
public static void TellMeAboutYourself()
{
Identifiers theAttribute = (Identifiers)Attribute.GetCustomAttribute(typeof(SomeClass), typeof(Identifiers));
foreach (var s in theAttribute.Names)
{
Console.WriteLine(s);
}
}
}
}
I'm not sure if I am abusing Enums here. Maybe this is not the best design approach.
I have a enum which declares the possible parameters to method which executes batch files.
public enum BatchFile
{
batch1,
batch2
}
I then have my method:
public void ExecuteBatch(BatchFile batchFile)
{
string batchFileName;
...
switch (batchFile)
{
case BatchFile.batch1:
batchFileName = "Batch1.bat";
break;
case BatchFile.batch2:
batchFileName = "Batch2.bat";
break;
default:
break;
}
...
ExecuteBatchFile(batchFileName);
}
So I was wondering if this is sound design.
Another option I was thinking was creating a Dictionary<> in the constructor like this:
Dictionary<BatchFile, String> batchFileName = new Dictionary<BatchFile, string>();
batchFileName.Add(BatchFile.batch1, "batch1.bat");
batchFileName.Add(BatchFile.batch2, "batch2.bat");
Then instead of using a switch statement I would just go:
public void ExecuteBatch(BatchFile batchFile)
{
ExecuteBatchFile(batchFileName[batchFile]);
}
I'm guessing the latter is the better approach.
I'd probably go for a design along these lines:
public interface IBatchFile
{
void Execute();
}
public class BatchFileType1 : IBatchFile
{
private string _filename;
public BatchFileType1(string filename)
{
_filename = filename;
}
...
public void Execute()
{
...
}
}
public class BatchFileType2 : IBatchFile
{
private string _filename;
public BatchFileType2(string filename)
{
_filename = filename;
}
...
public void Execute()
{
...
}
}
In fact, I'd extract any common functionality into a BatchFile base class
What if you suddenly need a third batch file? You have to modify your code, recompile your library and everybody who uses it, has to do the same.
Whenever I find myself writing magic strings that might change, I consider putting them into an extra configuration file, keeping the data out of the code.
I would personally use a static class of constants in this case:
public static class BatchFiles
{
public const string batch1 = "batch1.bat";
public const string batch2 = "batch2.bat";
}
If you want to use an enum then you may want to consider utilising attributes so you can store additional inforation (such as the file name) against the elements.
Here's some sample code to demonstrate how to declare the attributes:
using System;
public enum BatchFile
{
[BatchFile("Batch1.bat")]
batch1,
[BatchFile("Batch2.bat")]
batch2
}
public class BatchFileAttribute : Attribute
{
public string FileName;
public BatchFileAttribute(string fileName) { FileName = fileName; }
}
public class Test
{
public static string GetFileName(Enum enumConstant)
{
if (enumConstant == null)
return string.Empty;
System.Reflection.FieldInfo fi = enumConstant.GetType().GetField(enumConstant.ToString());
BatchFileAttribute[] aattr = ((BatchFileAttribute[])(fi.GetCustomAttributes(typeof(BatchFileAttribute), false)));
if (aattr.Length > 0)
return aattr[0].FileName;
else
return enumConstant.ToString();
}
}
To get the file name simply call:
string fileName = Test.GetFileName(BatchFile.batch1);
I think the latter approach is better because it separates out concerns. You have a method which is dedicated to associating the enum values with a physical path and a separate method for actually executing the result. The first attempt mixed these two approaches slightly.
However I think that using a switch statement to get the path is also a valid approach. Enums are in many ways meant to be switched upon.
Using enums is ok if you don't need to add new batch files without recompiling / redeploying your application... however I think most flexible approach is to define a list of key / filename pairs in your config.
To add a new batch file you just add it to the config file / restart / tell your user the key. You just need to handle unknown key / file not found exceptions.
Is it really necessary that ExecuteBatch works on limited number of possible file names only?
Why don't you just make it
public void ExecuteBatch(string batchFile)
{
ExecuteBatchFile(batchFile);
}
The problem with the latter case is if something passed an invalid value that is not inside the dictionary. The default inside the switch statement provides an easy way out.
But...if you're enum is going to have a lot of entries. Dictionary might be a better way to go.
Either way, I'd recommend some way to provide protection of the input value from causing a bad error even in ammoQ's answer.
The second approach is better, because it links the batch file objects (enums) with the strings..
But talking about design, it would not be very good to keep the enum and the dictionary separate; you could consider this as an alternative:
public class BatchFile {
private batchFileName;
private BatchFile(String filename) {
this.batchFileName = filename;
}
public const static BatchFile batch1 = new BatchFile("file1");
public const static BatchFile batch2 = new BatchFile("file2");
public String getFileName() { return batchFileName; }
}
You can choose to keep the constructor private, or make it public.
Cheers,
jrh.
The first solution (the switch) is simple and straight forward, and you really don't have to make it more complicated than that.
An alternative to using an enum could be to use properties that returns instances of a class with the relevant data set. This is quite expandable; if you later on need the Execute method to work differently for some batches, you can just let a property return a subclass with a different implementation and it's still called in the same way.
public class BatchFile {
private string _fileName;
private BatchFile(string fileName) {
_fileName = fileName;
}
public BatchFile Batch1 { get { return new BatchFile("Batch1.bat"); } }
public BatchFile Batch2 { get { return new BatchFile("Batch2.bat"); } }
public virtual void Execute() {
ExecuteBatchFile(_fileName);
}
}
Usage:
BatchFile.Batch1.Execute();
Alright, i dont know how to explain it well.. but i have a switch statement,
string mystring = "hello";
switch(mystring)
{
case "hello":
break;
case "goodbye":
break;
case "example":
break;
}
of course this is an example, and in the real situation, there will be different things happening for each case.
ok, hope you get the point, now, doing this manually is impossible, because of the sheer number of different case's. i need to respectively create a list, of all the cases, so for instance.. for the above switch statement, i would need
string[] list = { "hello", "goodbye", "example" };
maybe could be done with a foreach some how i dont know, any help would be greatly appreciated.
also, any working codes provided would be awesome!
edit:
people are asking for more detail, so here is how it works.
the user of the program, inputs a series of strings.
based on the string(s) they entered, it will do a few if's and else if's and throw back the new strings basically. i need to be able to be able to create a list, through the program, of all the options available to use. and i cant just make a list and hard code it in, because im always adding more case's to the statement, and i cant be going back and keeping a list up to date.
FOR VISUAL STUDIO:
if mystring is an enum instead of a string, in visual studio, if you type "switch" [TAB] "mystring" [ENTER] it'll build the long switch for you with all the cases.
It depends on how clever you want to get... You could create a custom attribute that attaches to a method with the string that method should handle. Then, instead of a switch statement, you would just find the attribute with your desired value and execute it.
using System;
using System.Reflection;
namespace ConsoleApplication1 {
[AttributeUsage(AttributeTargets.Method)]
internal class ProvidesAttribute : Attribute {
private String[] _strings;
public ProvidesAttribute(params String[] strings) {
_strings = strings;
}
public bool Contains(String str) {
foreach (String test in _strings) {
if (test.Equals(str)) {
return true;
}
}
return false;
}
}
internal class Program {
[Provides("hello", "goodbye")]
public void HandleSomeStuff(String str) {
Console.WriteLine("some stuff: {0}", str);
}
[Provides("this")]
public void HandleMoreStuff(String str) {
Console.WriteLine("more stuff: {0}", str);
}
public void HandleString(String str) {
// we could loop through each Type in the assembly here instead of just looking at the
// methods of Program; this would allow us to push our "providers" out to other classes
MethodInfo[] methods = typeof(Program).GetMethods();
foreach (MethodInfo method in methods) {
Attribute attr = Attribute.GetCustomAttribute(method, typeof(ProvidesAttribute));
ProvidesAttribute prov = attr as ProvidesAttribute;
if ((prov != null) && (prov.Contains(str))) {
method.Invoke(this, new Object[] { str } );
break; // removing this enables multiple "providers"
}
}
}
internal static void Main(String[] args) {
Program prog = new Program();
foreach (String str in args) {
prog.HandleString(str);
}
}
}
}
Once you have the framework, you wouldn't need to alter the HandleString() code, just add the methods you want to take care of and set the Provides attribute on them. If you wanted to extend the idea a little further, you could create multiple classes to handle a wide variety of strings, then loop through each type in your assembly looking for the Provides attribute.
EDIT this has the added benefit that you can define multiple methods that act on the same string (by removing the break in the loop logic).
I'm note sure what you are trying to do, but you might be able to use a dictionary.
Dictionary<string, int> lookupTable = new Dictionary<string, int>();
lookupTable.Add("hello", 1);
lookupTable.Add("goodbye", 2);
lookupTable.Add("example", 3);
int output = lookupTable["hello"];
You wouldn't need to have code to add each individual entry. You could read in the keys and values from a file, loop though them and populate the dictionary.
If you explain more about what you are trying to do, we could give you more specific advice.
By proper refactoring (your hypothetical example) you can make sure that out of your sheer number of cases, there will be a lot of them that can call the same sub routine with their string parameter.
In many of these scenarios, you may not even need a huge switch statement, but just parameterize one sub routine that can handle them.
Without a concrete example of what you want to do in the case statements, it is hard to come up with a concrete answer.
You appear to be trying to extract "command strings" from your code, so that you can automatically update the list of available commands in your user documentation. I think this will not gain you much, as you will still need to manually document what each command does.
That being said, the following powershell command will extract the data you want from test.cs:
type test.cs|select-string 'case "(.*)"'|foreach {$_.Matches[0].Groups[1].Value}
Switch statements evaluate on constants, so the case statements won't work with variables. Perhaps you should consider using a Dictionary<> and branching based on that. But without any more insight into the problem you're solving, there's little point in saying anything more.
Create an abstract class, call it something like StringHandler. Give it 2 abstract methods, 1 to check whether the handler can handle the string, then the other to do the processing. Something like:
public abstract class StringHandler
{
public abstract bool CanProcess(string input);
public abstract void Process();
}
public class HelloStringHandler : StringHandler
{
public override bool CanProcess(string input)
{
return input.Equals("hello");
}
public override void Process()
{
Console.WriteLine("HELLO WORLD");
}
}
Then in your main class you can do a simple loop with a list of all known handlers, like
List<StringHandler> handlers = new List<StringHandler>();
handlers.Add(new HelloStringHandler());
string myString = "hello";
foreach (StringHandler handler in handlers)
{
if (handler.CanProcess(myString))
{
handler.Process();
break;
}
}
All this can be optimised/improved obviously, but I hope you get the picture?
I am very rusty at c#, but this was a fun little exercise. The following code is not very clean, but will do what you asked. You will want to add more checks, use the variables better and add more logic, but this should help you get going in the right direction.
var newfile = System.IO.File.CreateText("newcode.txt");
newfile.Write("string[] list = { ");
using (var file = System.IO.File.OpenText("code.txt"))
{
bool bFirst = true;
while (!file.EndOfStream)
{
String line = file.ReadLine();
if (line.Contains("case ") && line.EndsWith(":"))
{
line = line.Replace("case", " ");
line = line.Replace(":", " ");
line = line.Trim();
if (bFirst == false)
{
newfile.Write(", ");
}
bFirst = false;
newfile.Write(line);
}
}
}
newfile.WriteLine(" };");
newfile.Close();
Good luck!
Inspired by #Jheddings answer, I came up with this. Maybe it's over the top, but at least I had fun figuring it out:
Main benefits over jheddings solution:
Uses extension methods, no utility class instance needed.
Reflection lookup of all candidate methods is done only once, right before the first string is evaluated. Afterwards, it is a simple lookup and invoke.
Even simpler usage
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
namespace StringSwitcher
{
class Program
{
static void Main(string[] args)
{
"noAction".Execute(); //No action, since no corresponding method defined
"Hello".Execute(); //Calls Greet method
"world".Execute(); //Calls Shout method
"example".Execute(); //Calls Shout method
Console.ReadKey();
}
//Handles only one keyword
[Keywords("Hello")]
static public void Greet(string s)
{
Console.WriteLine(s + " world!");
}
//Handles multiple keywords
[Keywords("world", "example")]
static public void Shout(string s)
{
Console.WriteLine(s + "!!");
}
}
internal static class ActionBrokerExtensions
{
static Dictionary<string, MethodInfo> actions;
static ActionBrokerExtensions()
{
//Initialize lookup mechanism once upon first Execute() call
actions = new Dictionary<string, MethodInfo>();
//Find out which class is using this extension
Type type = new StackTrace(2).GetFrame(0).GetMethod().DeclaringType;
//Get all methods with proper attribute and signature
var methods = type.GetMethods().Where(
method => Attribute.GetCustomAttribute(method, typeof(KeywordsAttribute)) is KeywordsAttribute &&
method.GetParameters().Length == 1 &&
method.GetParameters()[0].ParameterType.Equals(typeof(string)));
//Fill the dictionary
foreach (var m in methods)
{
var att = (Attribute.GetCustomAttribute(m, typeof(KeywordsAttribute)) as KeywordsAttribute);
foreach (string str in att.Keywords)
{
actions.Add(str, m);
}
}
}
public static void Execute(this string input)
{
//Invoke method registered with keyword
MethodInfo mi;
if (actions.TryGetValue(input, out mi))
{
mi.Invoke(null, new[] { input });
}
}
}
[AttributeUsage(AttributeTargets.Method)]
internal class KeywordsAttribute : Attribute
{
private ICollection<string> keywords;
public KeywordsAttribute(params String[] strings)
{
keywords = new List<string>(strings);
}
public ICollection<string> Keywords
{
get { return keywords; }
}
}
}
Apologies for any strange rendering, for some reason the syntax highlighting chokes on the code :-(