Context :
Since we are developing in C# MVC3, we wanted to have some classes designed to handle the tables on a web page. (Pagination / search / etc...).
So we finally found that it could be the best to have the following classes :
The table object that will hold all other object and knows the current page / current search etc... (misc informations)
public class Table<T> where T : IPrivateObject
{
...
public ICollection<Column<T>> Columns { get; set; }
public ICollection<Row<T>> Rows { get; set; }
public ICollection<RowMenu<T>> Menus { get; set; }
public ICollection<T> Items { get; set; }
public Table(
ICollection<T> inputItems,
ICollection<Column<T>> columns,
ICollection<RowMenuItem<T>> rowMenuItems,
...)
{
...
this.Columns = columns;
}
The column object that knows which property should be displayed and and a header value
public class Column<T> where T : IPrivateObject
{
public string Value { get; set; }
public Expression<Func<T, object>> Property { get; set; }
public Column(Expression<Func<T, object>> property, string value)
{
this.Property = property;
this.Value = value;
}
}
The other classes are not really interesting so i won't post them here.
In the controller, we use these classes like that :
public ActionResult Index(string search = null, string sort = null, int order = 1, int take = 10, int page = 1)
{
ICollection<Person> people = prismaManager.PersonManager.Search(search);
ICollection<Column<Person>> columns= new List<Column<Person>>();
columns.Add(new Column<Person>(Person => Person, "Person"));
columns.Add(new Column<Person>(Person => Person.LastMembershipApproval, "Last Membership approval"));
Table<Person> table = people.ToTable(columns);
}
We are now writing a helper that will display the table correctly.
It works well for the header but we face a problem with the Expressions when we want to use the #Html.DisplayFor() helper.
This is what we currently have for the content :
private static string TableRows<T>(HtmlHelper<Table<T>> helper, Table<T> table) where T : IPrivateObject
{
StringBuilder sb = new StringBuilder();
foreach (var item in table.Items)
{
sb.AppendLine("<tr>");
foreach (var column in table.Columns)
{
sb.AppendLine("<td>");
sb.AppendLine(helper.DisplayFor(obj => ??? ).ToString()); // How should I use the Expression that is stored in the column but for the current element ?
sb.AppendLine("</td>");
}
sb.AppendLine("</tr>");
}
return sb.ToString();
}
For this to work, we should set the value of the "Person" parameter from the Expression stored in the column to the current item.
new Column<Person>(Person => Person, "Person"));
How are we supposed to do that ?
Should we (if it is possible) modify the expression to set the value ?
Should we recreate a new Expression using the old one as a basic expression ?
I've been searching for 3 days now and I can't find any answers.
Thanks for your help.
UPDATE :
The problem is (as #Groo & #Darin Dimitrov said) that the Helper is of type HtmlHelper> and not HtmlHelper.
Any idea how I could get an HtmlHelper from a HtmlHelper> ?
UPDATE :
Person class is as following :
public class Person : IPrivateObject
{
public int Id { get; set; }
public int? AddrId { get; set; }
[DisplayName("First Name")]
[StringLength(100)]
[Required]
public string FirstName { get; set; }
[DisplayName("Last Name")]
[StringLength(100)]
[Required]
public string LastName { get; set; }
[DisplayName("Initials")]
[StringLength(6)]
public string Initials { get; set; }
[DisplayName("Last membership approval")]
public Nullable<DateTime> LastMembershipApproval { get; set; }
[DisplayName("Full name")]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
public override string ToString()
{
return FullName;
}
}
Here's how you could proceed. Start by writing a custom view data container implementation which could be as simple as:
public class ViewDataContainer : IViewDataContainer
{
public ViewDataContainer(ViewDataDictionary viewData)
{
ViewData = viewData;
}
public ViewDataDictionary ViewData { get; set; }
}
and then just instantiate a HtmlHelper<T> which is what you need:
private static string TableRows<T>(HtmlHelper<Table<T>> helper, Table<T> table) where T : IPrivateObject
{
var sb = new StringBuilder();
sb.AppendLine("<table>");
foreach (var item in table.Items)
{
sb.AppendLine("<tr>");
foreach (var column in table.Columns)
{
var viewData = new ViewDataDictionary<T>(item);
var viewContext = new ViewContext(
helper.ViewContext.Controller.ControllerContext,
helper.ViewContext.View,
new ViewDataDictionary<T>(item),
helper.ViewContext.Controller.TempData,
helper.ViewContext.Writer
);
var viewDataContainer = new ViewDataContainer(viewData);
var itemHelper = new HtmlHelper<T>(viewContext, viewDataContainer);
sb.AppendLine("<td>");
sb.AppendLine(itemHelper.DisplayFor(column.Property));
sb.AppendLine("</td>");
}
sb.AppendLine("</tr>");
}
sb.AppendLine("</table>");
return sb.ToString();
}
UPDATE:
The previous example doesn't handle value types because the expression in the column is of type Expression<Func<T, object>> and when you are pointing to a value type property the value will be boxed and ASP.NET MVC doesn't allow such expressions to be used with the template helpers. To remedy this problem one possibility is to test whether the value was boxed and extract the actual type:
sb.AppendLine("<td>");
var unary = column.Property.Body as UnaryExpression;
if (unary != null && unary.NodeType == ExpressionType.Convert)
{
var lambda = Expression.Lambda(unary.Operand, column.Property.Parameters[0]);
sb.AppendLine(itemHelper.Display(ExpressionHelper.GetExpressionText(lambda)).ToHtmlString());
}
else
{
sb.AppendLine(itemHelper.DisplayFor(column.Property).ToHtmlString());
}
sb.AppendLine("</td>");
There are several things you should change.
The thing that first surprised me is that your table both has a list of Columns and Rows. You should change the design to something like: a Table has a list of Rows, and each Row has a list of Columns (or vice versa).
But this remark is less relevant. I guess a "Column" is something like a "Column definition" and contains no data, but in that case I see no point in having ICollection<Row<T>> instead of just ICollection<T>.
Next, you probably want to store a delegate, like Func<T, object>, instead of an Expression<Func<T, object>>.
Property should at least have private setters (or, even better, readonly backing fields). This is not something that you would want other parts of your code to change.
Naming is very confusing IMHO. I would choose better property names. If I got you right, Value and Property should actually be called HeaderName and GetValue, respectively.
Having said all that, I would change Column to something like this:
public class Column<T> where T : IPrivateObject
{
private readonly string _name;
private readonly Func<T, object> _valueGetter;
/// <summary>
/// Gets the column name.
/// </summary>
public string Name
{
get { return _name; }
}
/// <summary>
/// Gets the value of this column from the
/// specified object.
/// </summary>
/// <param name="obj">The object.</param>
/// <returns></returns>
public object GetValueFrom(T obj)
{
return _valueGetter(obj);
}
public Column(string columnName, Func<T, object> valueGetter)
{
_name = columnName;
_valueGetter = valueGetter;
}
}
And then simply use this in your loop:
sb.AppendLine(column.GetValueFrom(item).ToString());
You need to compile the expression using expression.Compile() (you have the property expression in your column.Property). This will give you a delegate. You can pass the object there and get the value. You also will need to pass the person, or the T, to the helper method.
Related
I have the following object:
public class ContactImport {
public long Id {get;set;}
public Contact Contact {get;set;}
public Company Company {get;set;}
public Address Address {get;set;}
}
I want to be able to set the properties on the the nested objects dynamically based on an expression passed in (Expression<Func<T, dynamic>>).
To do this I have the following method, this works fine for setting properties on the top level object (such as Id) but fails when trying to set anything on the nested objects (such as Contact.FirstName)
public static void SetPropertyValue<T, TProp>(this T target, Expression<Func<T, TProp>> member, TProp value) {
var selectorExpr = (MemberExpression)(member.Body is UnaryExpression ? ((UnaryExpression)member.Body).Operand : member.Body);
if (selectorExpr != null) {
var property = selectorExpr.Member as PropertyInfo;
if (property != null) {
property.SetValue(target, value);
}
}
}
It looks like it's trying to set the property on the top level object but can't. I take it this is possible but I'm unsure how to achieve it with what I currently have.
The SetPropertyValue method is invoke like this:
public class ImportCheck<T> {
public int id { get; set; }
public string Name { get; set; }
public Type Type { get; set; }
public bool Required { get; set; }
public int? MinLength { get; set; }
public int? MaxLength { get; set; }
public string Value { get; set; }
public Expression<Func<T, dynamic>> AssociatedProperty { get; set; }
}
T pt = (T)Activator.CreateInstance(typeof(T));
foreach (var m in mapping) {
pt.SetPropertyValue(m.AssociatedProperty, Convert.ChangeType(m.Value, Nullable.GetUnderlyingType(m.Type) ?? m.Type));
}
In the above example T is ContactImport, m.AssociatedProperty is the expression and mapping is a List<ImportCheck<ContactImport>>.
Update
My issue seems to boil down to the fact that the expression being passed into SetPropertyValue has a return type of dynamic. If this is set to int and the property on the nested object is an int then it all works. The problem I have then is that I need to explicitly set the result of the expression to match the type of the target property. This however leaves me with another issue in that I need a list of ImportChecks with the possibility of each Expression<Func<T,dynamic>> having a different return type.
I have an object containing different properties like the object below:
public class CompressedLogResponse
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
public List<Log> Log{ get; set; }
}
How can I return a List of this objekt that does not include the List<Log> Log property?
Linq would be preffered
Thanks for any help that you can provide
You cannot just hide a property of a class (you declared it a as public)
Option 1:
Althought as Robson wrote you can set it null (thats not very reliable thaught cause nobody expects a class containing a property that is always null)
Option2:
If you consume the class on the same place use a anonymous type as Mez wrote, althought it sounds like you want to hide the Property from external usage. (I don't like the dynamic approach, the dynamic keyword was made for interop/DOM not for transporting anonymous types.)
Option3:
If you want a List of this type to be returned without the Log property, you have to create a new class (Inheritance is a good way to realize this):
public class CompressedLogResponseBase
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
}
public class CompressedLogResponse : CompressedLogResponseBase
{
public List<Log> Log{ get; set; }
}
Now you can return a list of base items (that do not have a Log property at all)
public List<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return ((IEnumerable<CompressedLogResponseBase>)items).ToList();
}
If a IEnumerable as return type is suficient it becomes really easy
public IEnumerable<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return items
}
whith "does not include the List Log property" i guess you mean that the property "public List Log" will be blanked but still there, so you can just null that property out, because if you create an object that doesn't contain the "public List Log" property, than it will not be a "CompressedLogResponse" but will be another type.
List<CompressedLogResponse> listOne = new List<CompressedLogResponse>();
//....
//fill the listOne
//....
List<CompressedLogResponse> listWithoutListLog = (from item in listOne
select new CompressedLogResponse(
LoggerType = item.LoggerType,
NumberOfRegisters = item.NumberOfRegisters ,
NewLogId = item.NewLogId ,
LoggerAnnounceTime = item.LoggerAnnounceTime ,
Log= null)).ToList();
You can return an anonymous list of your original list like the following;
public static List<dynamic> Test() {
List<CompressedLogResponse> list = new List<CompressedLogResponse>();
var result = list.Select(x => new
{
x.LoggerAnnounceTime,
x.LoggerType,
x.NewLogId,
x.NumberOfRegisters
});
return result.ToList<dynamic>();
}
Take a look at the .Select(), and also the dynamic keyword.
Then to call it,
var x = Test();
foreach(dynamic o in x)
{
int NumberOfRegisters;
//You have 2 ways... either by
NumberOfRegisters = o.NumberOfRegisters;
// or reflection
NumberOfRegisters = o.GetType().GetProperty("NumberOfRegisters").GetValue(o, null);
}
Let's assume we have a class called "Tag".
public class Tag
{
public string Name { get; private set; }
public string Description { get; private set; }
public Type Type { get; private set; }
public Tag(string name, string description, Type type)
{
this.Name = name;
this.Description = description;
this.Type = type;
}
}
An example of an instance of a Tag would be:
Tag weightTag = new Tag("Weight", "Weight of item in kg", typeof(double))
Next assume that I have another class which has a collection of these Tags which a value relevant to that object mapped to each individual tag in the collection.
public class Item
{
public string Id { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public Dictionary<Tag, object> Tags { get; private set; }
public Item(string name, string description)
{
this.Name = name;
this.Description = description;
this.Tags = new Dictionary<Tag, object>();
}
public void AddTag(Tag tag, object value)
{
Tags.Add(tag, value);
}
}
I like this method due to the fact that you can take some predefined tags from some where and then just assign a value.
Tag buildDateTag = TagProvider.GetByName("BuildDate");
Tag weightTag = TagProvider.GetByName("Weight");
item.AddTag(buildDateTag, new DateTime(2013,12,06);
item.AddTag(weightTag, 10.5);
The downside to this method is that there will be a lot of boxing/unboxing. For instance, if I have a collection of Item and I want to sum all the values of the tag corresponding to weight I'd have to do something like:
double totalWeight = 0d;
foreach (var item in items)
{
if (Tags.ContainsKey(weightTag))
{
totalWeight += (double)Tags[weightTag];
}
}
In this instance I happened to know that I'm going to cast to double so the only performance penalty was the unboxing. However there may be instances where I will need to get the type of the object from the Type member in the Tag object in order to figure out what the type of the value object is.
My question is do you think there is a better way to architect this in order to get rid of the need to rely on using objects and unboxing everything every time I want to use a value?
And although this should probably be a different question, in this usage should Tag be a struct rather than a class?
IMHO, you can use an interface that has some of the common properties for the objects that you are expecting to be as part of the objects that you can tag against.
In that case, you can accept any object that Implements your interface and hence, you will have a neat and a cleaner code
Sample :
class BuildDateTag : ITaggable
{
int id;
string name;
double weight;
}
this way, you can have the tags defined inside the Item class from
public Dictionary<Tag, object> Tags { get; private set; }
to public Dictionary<Tag,ITaggable> Tags{get;set;}
Consider this and post the queries and your feasibility w.r.to this suggestion
I've got a set of classes with propperties and a main class which has lists of the set of classes.
public class MainClass
{
public List<ClassA> listA {get;set;}
public List<ClassB> listB {get;set;}
public List<ClassC> listC {get;set;}
public object[] loop = {listA, listB, listC};
}
class ClassA
{
public Guid id {get;set;}
public string text {get;set;}
public int number {get;set}
public status {get;set;}
public object[] loop = {id, text, number};
}
class ClassB
{
public Guid id {get;set;}
public string text {get;set;}
public Image pic {get;set}
public status {get;set;}
public object[] loop = {id, text, pic};
}
class ClassC
{
public Guid id {get;set;}
public byte[] data {get;set;}
public DateTime date {get;set;}
public status {get;set;}
public object[] loop = {id, data, date};
}
public enum status
{
nothing=0, instert=1, delete=2, edit=3
}
Situation has changed since yesterday but still, i'd like to index my class, my idea was by adding this line:
public object[] loop = {listA, listB, listC};
to MainClass, archieving this goal, after changing the whole thing to an non static class it seems forbidden. also when i was trying this with a static class i cant adress my lists directly. could this be done any how?
finaly i want to adress a specific property inside the list like this:
MainClass mc = new MainClass();
DateTime dt = mc.loop[2][5].loop[2];
even if it would be nicer to do this without the loop property, like:
DateTime dt = mc[2][5][2];
how i want to loop it finaly:
for(int i=0; i<mc.loop.count(); i++)
{
for (int j=0; j<mc.loop[i].Count(); i++)
{
switch(mc.loop[i][j].loop[3])
{
case: delete
doSomething1(mc.loop[i][j])
case: insert
doSomething2(mc.loop[i][j])
case: edit
doSomething3(mc.loop[i][j])
default
break;
}
}
}
As I've written in my comment, you should simply go for a Object-Relational Mapping framework, since you are obviously trying to abstract the mapping from your domain into the database.
That being said, you can generalize the whole thing using Reflection. Provided that you don't intend to add complex mapping rules, you would have something similar to:
foreach (var propertyInfo in myClass.GetType().GetProperties())
{
var name = propertyInfo.Name;
var value = propertyInfo.GetValue(myClass);
// do stuff
Console.WriteLine("Value of {0} is {1}", name, value ?? "null");
}
A proper ORM does a lot more than this. If allows you to define specific mapping rules for each property. Nested objects and automatic mapping of one-to-many relations. It does lots of complex caching to avoid performance penalty associated with reflection (and more important, database access). It allows lazy access to the database by deferring queries until data is needed. It tracks which properties are changed and automatically updates them. And all that by including a reference to a library, spending a day or two looking at examples (and asking stuff on Stack Overflow) and writing a mapping configuration file.
Or, you can define mappings through code to get full intellisense and better type safety:
// fluent nhibernate example
public class CatMap : ClassMap<Cat>
{
public CatMap()
{
// define which properties are going to be saved, and how
Id(x => x.Id);
Map(x => x.Name).Length(16).Not.Nullable();
Map(x => x.Sex);
References(x => x.Mate);
HasMany(x => x.Kittens);
}
}
What you are doing right now is a maintenance nightmare. You are enforcing a rule where each data class needs to expose its properties as an object array (and think about how you would update their values this way). Also, you lose all type safety because you end up with plain objects. The only way for you to know which property you are accessing is by the index of the loop array, meaning you are going for lots of if conditions and magic numbers all over your code. As an exercise of how things shouldn't be done, it's fine, but don't allow this to end up in production code or you will spend countless hours fixing bugs and changing code to add new functionality.
try something like this:
MainClass mc = new MainClass();
DateTime dt = ((ClassA) mc.loop[2]).date;
Still I am not sure what you really want and what are all those indexes for...
1) to discard the loop variable you can create class indexer like this
private object[] loop = {id, text, number};
public int this[int index]
{
get { return loop[index]; }
set { loop[index] = value; }
}
2) to be able to retrieve the variables you would probably have to cast them from object to their actual types to be able to use their capabilities. it is still unpractical.
DateTime dt = ((DateTime) ((ClassA)mc[0]) [2]);
Ok, not sure what you are doing but how about this
public enum Status
{
Nothing = 0,
Insert,
Delete,
Edit
}
public abstract class Searchable
{
public virtual Guid Id { get; set; }
public virtual Status Status { get; set; }
protected internal abstract IEnumerable SearchableProperties { get; }
}
public class ClassA : Searchable
{
public string Text { get; set; }
public int Number { get; set; }
protected internal override IEnumerable SearchableProperties
{
get
{
yield return Text;
yield return Number;
}
}
}
public class ClassB : Searchable
{
public string Text { get; set; }
public Image Pic { get; set; }
protected internal override IEnumerable SearchableProperties
{
get
{
yield return Text;
yield return Pic;
}
}
}
public class ClassC : Searchable
{
public byte[] Data { get; set; }
public DateTime Date { get; set; }
protected internal override IEnumerable SearchableProperties
{
get
{
yield return Data;
yield return Date;
}
}
}
Then you can write your main class like this,
public class Searchables
{
public List<ClassA> ListA { get; set; }
public List<ClassB> ListB { get; set; }
public List<ClassC> ListC { get; set; }
public void SearchContents(Action<Status, Searchable, object> visitor)
{
SearchContent(this.ListA, visitor);
SearchContent(this.ListB, visitor);
SearchContent(this.ListC, visitor);
}
private static void SearchContent(
IEnumerable<Searchable> searchees,
Action<Status, Searchable, object> visitor)
{
foreach (var searchee in searchees)
{
visitor(searchee.Status, searchee, searchee.Id);
foreach (var property in searchee.SearchableProperties)
{
visitor(searchee.Status, searchee, property);
}
}
}
}
Then all you have to do is write the visitor ...
var mainClass = new Searchables();
....
mainClass.SearchContent((status, searchee, property) =>
{
switch(status)
{
case Status.Delete:
// DoSomthing1 ...
break;
}
});
but, that bit is not in your question.
I'm looking to incorporate property value translations into my QueryOver queries.
I like writing queries following the Query Object Pattern, directly producing MVC view models. In my view models, I try to use property types that are as simple as possible, keeping conversion complexity out of the views and controllers. This means that sometimes, I'll need to convert one type into another, such as dates into strings.
One could argue that such conversions should be performed in views but since most of my view models are directly translated to JSON objects, that would cause the conversion to become much more cumbersome. Performing date to string conversion in JavaScript is problematic at best and my JSON convertor is not flexible enough.
Here's an example of what I'm doing:
// Entity.
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public DateTimeOffset DateCreated { get; set; }
}
// View model.
public class CustomerViewModel
{
public string Name { get; set; }
public string DateCreated { get; set; } // Note the string type here.
}
// Query.
CustomerViewModel model = null;
List<CustomerViewModel> result = Session.QueryOver<Customer>()
.SelectList(list => list
.Select(n => n.Name).WithAlias(() => model.Name)
.Select(n => n.DateCreated).WithAlias(() => model.DateCreated))
.TransformUsing(Transformers.AliasToBean<CustomerViewModel>());
.Future<CustomerViewModel>()
.ToList();
When running the query code, the following exception is thrown:
Object of type 'System.DateTimeOffset' cannot be converted to type 'System.String'.
Obviously, this is because of the following line:
.Select(n => n.DateCreated).WithAlias(() => model.DateCreated))
So the question is: how to incorporate the date to string conversion into the query?
I don't want to perform the conversion after the query has executed because I would need an additional intermediate class to store the results before converting them.
List<CustomerViewModel> result = Session.QueryOver<Customer>(() => customerAlias)
.SelectList(list => list
.Select(n => customerAlias.Name).WithAlias(() => model.Name)
// I'm not sure if customerAlias works here or why you have declared it at all
.Select(Projections.Cast(NHibernateUtil.String, Projections.Property<Customer>(c => c.DateCreated))).WithAlias(() => model.DateCreated))
.TransformUsing(Transformers.AliasToBean<CustomerViewModel>());
.Future<CustomerViewModel>()
.ToList();
Should work but unfortunately does not give you any control over the format of the string. I've handled a similar problem by defining a private property on the model that holds the data as the correct type and a string property to return the formatted value, i.e.:
public class CustomerViewModel
{
public string Name { get; set; }
private DateTime DateCreatedImpl { get; set; }
public string DateCreated { get { return DateCreatedImpl.ToString(); }}
}
This has several advantages but might not work well with your JSON converter. Does your converter have a setting or attribute that would allow it to ignore private properties?
I came across the same problem today, and saw this posting. I went ahead and created my own transformer that can be given Converter functions to handle type conversions per property.
Here is the Transformer class.
public class AliasToDTOTransformer<D> : IResultTransformer where D: class, new()
{
//Keep a dictionary of converts from Source -> Dest types...
private readonly IDictionary<Tuple<Type, Type>, Func<object, object>> _converters;
public AliasToDTOTransformer()
{
_converters = _converters = new Dictionary<Tuple<Type, Type>, Func<object, object>>();
}
public void AddConverter<S,R>(Func<S,R> converter)
{
_converters[new Tuple<Type, Type>(typeof (S), typeof (R))] = s => (object) converter((S) s);
}
public object TransformTuple(object[] tuple, string[] aliases)
{
var dto = new D();
for (var i = 0; i < aliases.Length; i++)
{
var propinfo = dto.GetType().GetProperty(aliases[i]);
if (propinfo == null) continue;
var valueToSet = ConvertValue(propinfo.PropertyType, tuple[i]);
propinfo.SetValue(dto, valueToSet, null);
}
return dto;
}
private object ConvertValue(Type destinationType, object sourceValue)
{
//Approximate default(T) here
if (sourceValue == null)
return destinationType.IsValueType ? Activator.CreateInstance(destinationType) : null;
var sourceType = sourceValue.GetType();
var tuple = new Tuple<Type, Type>(sourceType, destinationType);
if (_converters.ContainsKey(tuple))
{
var func = _converters[tuple];
return Convert.ChangeType(func.Invoke(sourceValue), destinationType);
}
if (destinationType.IsAssignableFrom(sourceType))
return sourceValue;
return Convert.ToString(sourceValue); // I dunno... maybe throw an exception here instead?
}
public IList TransformList(IList collection)
{
return collection;
}
And here is how I use it, first my DTO:
public class EventDetailDTO : DescriptionDTO
{
public string Code { get; set; }
public string Start { get; set; }
public string End { get; set; }
public int Status { get; set; }
public string Comment { get; set; }
public int Client { get; set; }
public int BreakMinutes { get; set; }
public int CanBeViewedBy { get; set; }
}
Later on when I call my query, it returns Start and End as DateTime values. So this is how I actually use the converter.
var transformer = new AliasToDTOTransformer<EventDetailDTO>();
transformer.AddConverter((DateTime d) => d.ToString("g"));
Hope this helps.