How to configure automatic Table to IEnumerable<T> parameter conversion in SpecFlow? - c#

I have a lot of code that looks like this:
[Given(#"user amortizes the deductions:")]
public void GivenUserAmortizesTheDeductions(Table table) {
var tableRows = table.CreateSet<MyTableRow>();
}
It is repetative. I know I can create a [StepArgumentTransformation] to convert Table to IEnumerable<MyTableRow>, but it feels also too repetitive.
Question: Is there a way to configure SpecFlow to convert table to IEnumerable automatically without having to explicitly define this relationship every time?
To clarify, every time I add a new step that accepts yet another type of a row, I have to create a corresponding step transformation to support converting it into IEnumerable, i.e.:
[StepArgumentTransformation]
public static IEnumerable<FooRow> FooTable(Table table) {
return table.CreateSet<FooRow>();
}
[StepArgumentTransformation]
public static IEnumerable<BarRow> BarTable(Table table) {
return table.CreateSet<BarRow>();
}
I would like to say this thing once:
EnableGlobalSupportForConvertingATableToIEnumerableOfT();

Related

Best way to save type of class in database?

What is a good way to denote "type" in database?
I have a base class Action which is inherited by numerous child classes. Action has members like Id, Name etc all which corresponds to equivalent columns in a table in the database called action. So action table looks like this:
id | name | type
The type column denotes what action it is. In my code they correspond to the child classes deriving from parent Action. Now how do I save the type of class to the type field in database?
The type column in db could be of any data type.
Options:
Save action.GetType().ToString() as string in db. And get the action type from db back by converting the string representation of the type to its original type using reflection. But this will be problematic if class names change in future.
Create an enum to denote each child class and decorate it by a TypeAttribute, something like:
public abstract class Action
{
public enum Kind
{
[Type(typeof(ControlAction))]
ControlAction = 1,
[Type(typeof(UpdateAction))]
UpdateAction = 2,
etc
}
public abstract Kind ActionType { get; }
}
public class ControlAction : Action { public override Kind ActionType { get { return Kind.ControlAction; } } }
public class UpdateAction : Action { public override Kind ActionType { get { return Kind.UpdateAction; } } }
//etc
This looks good, except that for each class from here onwards I have to create an enum. And it feels like a little too much work to be done.
Build a separate static hash table of <int, Type> that ties a class to a int value. May be a little bit unreadable.
Is there a better solution to this?
I would go from the 3rd solution with a hash-table, as it does seem to be the cleaner design-wise. And I would delegate its management to the database!
After all, isn't this what relational databases excel at the most, creating relations between two entities (in your case, action and type)? Other advantage is you end up with a normalized schema (sure, so far, there is only one column to the type table, namely its name, but normalizing allows you to easily add additional attributes to the types should you need them in the future, which is why it is cleaner as a design).
The schema would be something like this:
Action table
action_id(PK) | name | type_id (int, FK to Type table)
Type table
type_id(PK) | type_name
Now you are safe if the name of a class changes in the future (concern from your first proposition with string type). Indeed, all you would do is change the type_name value in the corresponding Type table row and all your Action rows would still be linked to this row by the type_id, which never changes once created (no problem here, as it does not hold any "business meaning").
And you have your hash-table from 3 (the Type table) in a readable format as it is the RDMBS's responsibility to manage the keys of the hash-table (the type_id PK).
Note that you won't have to tie your class to an int value corresponding to the type_id column, but rather fetch from the Type table the type_id by looking it up against the Class type (type_name).
I ended up using option 2, but with less clutter of attributes. Something like this:
public abstract class Action
{
public enum Kind
{
ControlAction = 1,
UpdateAction = 2,
etc
}
public abstract Kind ActionType { get; }
}
public class ControlAction : Action { public override Kind ActionType { get { return Kind.ControlAction; } } }
public class UpdateAction : Action { public override Kind ActionType { get { return Kind.UpdateAction; } } }
The biggest advantage for this is that (even if it meant more typing), it enforces a numeric value to be associated with a class type.
Now class to int is just:
var value = (int)instance.ActionType;
Very fast.
But to convert int to class instance (or class type), I will have to create an instance of each sub action types, and compare its ActionType property to match the input int value. This is going to be slow. But I can cache somethings and make it faster. Something like:
static readonly Dictionary<Action.Kind, Type> actionTypes =
GetDefaultInstanceOfAllActions().ToDictionary(x => x.ActionType, x => x.GetType());
public static Action ToAction(this Action.Kind value)
{
return (Action)Activator.CreateInstance(actionTypes[value]);
}
The GetDefaultInstanceOfAllActions does some reflection (once) to get all types of actions (I use something like this answer for that). I can even make the make the instantiation faster by going the expression route.
The benefits:
Less hassle when creating a new class (no attributes).
Enforces an int to be tied to a class type.
Moderately fast with adequate caching.
I would go with your first option and use reflection. It seems more likely that you will want to add new action types rather than change existing class names and therefore the ease of serializing the type using reflection is more useful.
You could then just have a utility class for serializing actions and restoring them from their type string.

Using pluralised table names with C# generics in MVC

I'm trying to create a generic function that will be used to access multiple tables in my database. Is there a way to used pluralised (pluralized for the non-British!) table names with my generic function.
I may be thinking about this the wrong way (fairly new to generics/templates), but here's my code (Db is just a global var for access to my database):
public void UpdateMyTables<TEntity>() {
// string plural = EntityObject<TEntity>.GetTableName(); // OR SOMETHING SIMILAR??
IEnumerable<EntityType> entitiesToUpdate = Db.<TEntity>; // Obviously doesn't work because TEntity is not a table name, it's an object type
foreach(<TEntity> e in entitiesToUpdate) {
e.MyColumn = "A string that I'm updating all these fields with";
}
}
So my question is: do I need to do some hackery to get the pluralised table name, or is there a function designed to return this (like GetTableName), or should I come at this from a different angle?
I also found a link that would help with the manual conversion here: Pluralising in mvc
Hugs and kisses and thanks in advance...
You can use the .Set() method to get the IEnumerable:
IEnumerable<TEntity> entitiesToUpdate = Db.Set<TEntity>();
To get the Table Name you could possibly use the code from this blog post or this SO answer.
The foreach should be written:
foreach(TEntity e in entitiesToUpdate) { // you can use "var" here if you prefer
e.MyColumn = "A string that I'm updating all these fields with";
}
Now, the problem is that TEntity does not have a .MyColumn property. If you are using this method with entities that inherit from a base class (called for example BaseEntity), which has that property, you can change the method declaration like this:
public void UpdateMyTables<TEntity>() where TEntity : BaseEntity {
This limits you to pass to call this method only with Entities that inherits from BaseEntity, but will give you access to the public properties and methods defined in BaseEntity.
To make the code above work, Base Entity should be declared like this:
public class BaseEntity { //of course it can be abstract or an interface...
public string MyColumn { get; set; }
}
I hope I understood what you wanted to do. If you need further information let us know. :)

C# Dynamic Casting with GetType()

I've read many posts trying to accomplish similar tasks but cannot find a proper solution to my problem.
I'm trying to dynamically cast an object at runtime. (I know a lot of you are going to say it can't be done, and I'm not actually sure if it can...) My problem is that I have a dynamically created TreeView in a Windows Forms Application to display an Org Chart.
The data in the TreeView pulls from 3 tables: Departments, Jobs, Employees.
Importing the Tables as a Local DataSource gives me all 3 Tables as DataSet Objects, and templates for DataRow objects type casted to the table it comes from (including all columns as properties). (Similar to linq - except for Oracle DB)
I create TreeNode objects, use a description field from my DataRow as the TreeNode.Text Property and then attach the DataRow itself as the TreeNode.Tag property. This way, I can access the data from directly within the TreeNode simply by casting:
dsMyDataSource.DepartmentRow =
(dsMyDataSource.DepartmentRow)treeview1.SelectedNode.Tag;
I have a method that runs whenever the User selects a Node on treeview1 that populates a Details window with some of the underlying objects data. As of right now, I have a single method with a switch statement as such:
private doSomething()
{
switch(treeview1.SelectedNode.Tag.GetType().Name)
{
case "dsMyDataSource.DepartmentRow":
dsMyDataSource.DepartmentRow department =
(dsMyDataSource.DepartmentRow)treeview1.SelectedNode.Tag;
lblDetailsTitle = department.Title;
break;
case "dsMyDataSource.JobRow":
//etc...
}
}
What I want to do, is to have overloaded methods for each type and get rid of my switch statements. Like so:
this.doSomething(treeview1.SelectedNode.Tag);
Problem is, this returns a base object (thus the cast). But I don't know at compile time what type of TreeNode the User will select. Thus I want to be able to do something like:
this.doSomething((treeview1.SelectedNode.Tag.GetType())treeview1.SelectedNode.Tag);
private void doSomething(dsMyDataSource.DepartmentRow department)
{
lblDetailsTitle = department.Title;
// etc...
}
private void doSomething(dsMyDataSource.JobRow job) {..}
private void doSomething(dsMyDataSource.EmployeeRow employee) {..}
Is this possible?
You might find things cleaner if you use some meaningful objects rather than working directly off DataRows. In addition this will let you add a base class, which will make your casting problems go away.
So for example you could have
abstract class Selectable
{
public string Type { get; private set; }
public Selectable(string type) { Type = type; }
abstract void doSomething();
}
and then a type for each thing you want to select
class Department : Selectable{...}, class Job : Selectable{...}
To get the base types you will need one switch in a factory object.
public static class SelectableFactory
{
public static Selectable GetFromDataRow(DataRow dr)
{
Selectable res = null;
switch (dr.Type)
{
case "Department":
res = new Department(dr);
// etc ...
}
}
}
But you now have a collection of Selectables that can use polymorphism to do the action.
In addition to making your life easier it will make your code much easier to parse for anyone else that has to work on it in the future. It's also extensible, so when you need to add a DoSomethingElse method it's much easier to add for everything - or when you need a new type of datatable you don't disturb your UI code.

Should I make a method static that will be used across many aspx.cs files

I have a method with the following signature:
string GetTableCellValue(DataTable table, string columnName, int rowIndex){}
As you might guess, this method returns the value of the cell located at the specified column of the specified row of the specifies table in string format. It turns out that I need this methods almost in all the webpages. Here's my quetion(s):
Should I put this method in all the code files or?
Should I have it as a static method of some class, like Utilities_Class or?
Should I have it as a public NON-STATIC method of some class , like Utilities_Class?
The last 2 choices seem to be better idea. But I don't know which one to choose eventually.
You probably want to create a static method for this. Specifically, an extension method:
public static class Extensions
{
public static string GetTableCellValue(this DataTable table,
string columnName, int rowIndex)
{
// ...
}
}
Now, you can call it like an instance method on your DataTable objects:
DataTable dataTable = ...;
var value = dataTable.GetTableCellValue("column", row);
I would go for the second option as I wont require the instance of the class e.g Utilities_Class. GetTableCellValue has nothing to do with its data members or methods to making it static is quite reasonable. Make it extension method to call it just like it exists in DataTable class.
public static class DataExtensions
{
public static string GetTableCellValue(this DataTable table, string columnName, int rowIndex)
{
// implementation
}
}
You could also create it as an extension method, something like:
public static class DataExtensions
{
public static string GetTableCellValue(this DataTable table, string columnName, int rowIndex)
{
// implementation
}
}
None of those.
I would advise you to define your own Page (let's call it BasePage) that inherits from Page and add the method in the BasePage.
Every page of yours should be an instance of BasePage instead of the regular Page.
Edit:
As Daniel Hilgarth pointed out, extensions are a better choice than what i proposed.
Please, keep this post so that others will understand what not to do :)

Implementing sort/page feature when using POCOs with ASP.net Data Controls

I am not a big fan of datasets so I use POCO to return data. I have achieved paging and sorting using custom methods that I create for a POCO type that work on page size and give me a set of the complete POCO collection at a time, I use methods that check for name of the DataItem clicked and sort order to do that sort. Creating such methods over and over for every POCO that you plan to use with an ASP.net data control like Gridview is pretty painful.
Is there a technique to automate this so that I do not need to make such methods every time for a new POCO so that it works as if you were using a DataTable? I can provide some more explanation if required.
NOTE: Some people may call POCO as DTOs .
EDIT : I found this article on this topic. Is this the only possible way to get to what i am trying to do??
I agree with the base class idea as this will save all the duplicate code. One thing I did that takes a step in this direction is to create a class to handle the sorting of any generic list (for DTO/POCO). This allowed me to sort a list in my presenter or code-behind with only 1 line of code.
Typically for SortExpression I return the property name of the DTO you want to sort on. In addition, the SortDirection would be a simple "Ascending" Or "Decending"
List<Supplier> SupplierList = mSupplierService.GetSuppliers();
SupplierList.Sort(new GenericComparer<Supplier>(mView.SortExpression, mView.SortDirection));
mView.Suppliers = SupplierList;
Here is the class I used
public class GenericComparer<T> : IComparer<T>
{
private string mDirection;
private string mExpression;
public GenericComparer(string Expression, string Direction)
{
mExpression = Expression;
mDirection = Direction;
}
public int Compare(T x, T y)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(mExpression);
IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);
if (mDirection == "Ascending") {
return obj1.CompareTo(obj2);
}
else {
return obj2.CompareTo(obj1);
}
}
}
I created an Entity base class. My DAOs derive from it and have properties corresponding to the table columns (for the most part). My DAL returns List for any query and that is bindable to a GridView.

Categories

Resources