I have an interesting scenario and the answer isn't jumping out at me. I've looked for other similar questions but none seem to address this type of issue.
Before you ask, I do not have control over the source class layout.
My source object looks like this:
class Class1
{
string string1
string string2
string string3
string string4
string string5
string string6
}
class Class2
{
string foo
string bar
}
class Class3 //The source object!!
{
Class1 Inner1
Class2 Inner2
}
And my destination looks like this:
class Destination
{
string string1
string string2
string string3
string string4
string string5
string string6
string string7
}
In reality, Inner1 is a huge class and almost a perfect match - except for a couple exceptions. I'd like to use Automapper to directly copy everything from Inner1 to Destination using default matching, but also copy Inner2.foo to Destination.string6 and Inner2.bar to Destination.string7.
EDIT: I should add that right now I am mapping Inner1 to Destination and then doing a couple manual property copies outside of Automapper.
Any suggestions are appreciated.
Guessing you currently have something like this:
Mapper.CreateMap<Inner1, Destination>();
...
var inner1 = GetInner1();
var destination = Mapper.Map<Destination>(inner1);
// now do manual hydration on destination using inner2 instance...
You might be able to get away with this:
Mapper.CreateMap<Inner1, Destination>();
Mapper.CreateMap<Inner2, Destination>()
.ForMember(d => d.string6, o => o.ResolveUsing(s => s.foo))
.ForMember(d => d.string7, o => o.ResolveUsing(s => s.bar))
;
...
var inner1 = GetInner1();
var destination = Mapper.Map<Destination>(inner1);
var inner2 = GetInner2();
Mapper.Map(inner2, destination);
Related
With Couchbase's jsonObject we can create object with certain fields:
import com.couchbase.client.java.document.json.JsonObject
...
JsonObject content = JsonObject.create().put("some", "value");
The put function has several String & value options such as double, int, String etc, as can be seen here.
I was looking for a way to put a whole object in it. Something like:
Cat cat = new Cat(.....)
JsonObject content = JsonObject.create().put(cat);
Is there a way to do it and not to iterate over all of Cat's fields?
So here is how it can be done:
Cat cat = new Cat(...);
String asJson = gson.toJson(cat);
JsonObject.fromJson(asJson);
I have a folder with .pdf files. In the names of most files I want to replace specific string with another string.
Here's what I've written.
private void btnGetFiles_Click(object sender, EventArgs e)
{
string dir = tbGetFIles.Text;
List<string> FileNames = new List<string>();
DirectoryInfo DirInfo = new DirectoryInfo(dir);
foreach (FileInfo File in DirInfo.GetFiles())
{
FileNames.Add(File.Name);
}
lbFileNames.DataSource = FileNames;
}
Here I extract all file names in List Box.
private void btnReplace_Click(object sender, EventArgs e)
{
string strReplace = tbReplace.Text; // The existing string
string strWith = tbWith.Text; // The new string
string dir = tbGetFIles.Text;
DirectoryInfo DirInfo = new DirectoryInfo(dir);
FileInfo[] names = DirInfo.GetFiles();
foreach (FileInfo f in names)
{
if(f.Name.Contains(strReplace))
{
f.Name.Replace(strReplace, strWith);
}
}
And here I want to do the replacing, but something is going wrong. What?
It sounds like you want to change the name of the file on disk. If so then you need to use the File.Move API vs. changing the actual string which is the file name.
One other mistake you are making is the Replace call itself. A string in .Net is immutable and hence all of the mutating APIs like Replace return a new string vs. changing the old one in place. To see the change you need to assign the new value back to a variable
string newName = f.Name.Replace(strReplace, strWith);
File.Move(f.Name, newName);
f.Name is a read-only property. f.Name.Replace(..) simply returns a new string with the filename you want, but never actually changes the file.
I suggest something along the following, though I haven't tested it:
File.Move(f.Name, f.Name.Replace(strReplace, strWith));
Replace return another string, it doesn't change the original string.
So you need to write
string newName = f.Name.Replace(strReplace, strWith);
of course this doesn't change the name of the file on disk.
If that was your intention then you should look at
File.Move(f.Name, newName);
also keep in mind that File.Move will fail with an exception if the destination file exists.
See here for an example
At a first glance, seems like you're not reassigning the replaced string to your f.Name variable. Try this:
string NewFileName = f.Name.Replace(strReplace, strWith);
File.Copy(f.Name, NewFileName);
File.Delete(f.Name);
When you call string.Replace this doesn't alter your existing string. Instead it is returning a new string.
You need to change your code to something like this:
if(f.Name.Contains(strReplace))
{
string newFileName = f.Name.Replace(strReplace, strWith);
//and work here with your new string
}
Using Automapper, how do you handle the mapping of a property value on an object to an instance of a string. Basically I have a list of Role objects and I want to use Automapper to map the content of each "name" property to a corresponding list of string (so I just end up with a list of strings). I'm sure it has an obvious answer, but I can't find the mapping that I need to add to "CreateMap" to get it to work.
An example of the relevant code is shown below:
public class Role
{
public Guid Id{get;set;}
public string Name{get;set;}
...
...
}
// What goes in here?
Mapper.CreateMap<Role, string>().ForMember(....);
var allRoles = Mapper.Map<IList<Role>, IList<string>>(roles);
I love Automapper (and use it in a number of projects), but wouldn't this be easier with a simple LINQ statement?
var allRoles = from r in roles select r.Name
The AutoMapper way of accomplishing this:
Mapper.CreateMap<Role, String>().ConvertUsing(r => r.Name);
My site is using Subsonic 2.2 on my site.
I have 1 weird situation where I need to run some ad-hoc SQL statements.
public IList<string> GetDistincList(string TableName, string FieldName)
{
string sqlToRun = string.Format("SELECT DISTINCT {0} FROM {1} ORDER BY {0}", FieldName, TableName);
Query query = new Query(TableName);
query.PleaseRunThis(sqlToRun);
query.ExecuteReader();
}
Can anyone help me here? As it appears, I just want to return a generic list of strings.
Thanks!
Subsonic has a great method called ExecuteTypedList() so you can do somethink like this.
List<int> result = DB.Select(Table.Columns.Id)
.Distinct()
.From<Table>()
.OrderBy(Table.Columns.Id)
.ExecuteTypedList<int>();
or even with pocos:
public class UserResult
{
public int Id {get;set;}
public string Name {get;set;}
}
List<UserResult> users = DB.Select(
User.Columns.UserId + " as Id", // the as ... is only needed if your
User.Columns.UserName + " as Name" // column name differs from the
).From<User>() // property name of your class
.ExecuteTypedList<UserResult>();
Unfortunately this method doesn't work for string since it requires
a) a valuetype
b) a class with a parameterless constructor since the method uses reflection to map the columns from the result to the properties of the class
However I wrote an extension method a while ago that works for string:
Use the Subsonic.Select() ExecuteTypedList Method with String
Look at my own answer in the link.
If you add the extensionmethod to your code you can do:
List<String> result = DB.Select(User.Columns.UserName)
.From<User>()
.ExecuteTypedList();
Use the CodingHorror class.
Here's the SubSonic 3 way of doing it: http://www.subsonicproject.com/docs/CodingHorror
The SubSonic 2 way is similar:
Dim ch As SubSonic.CodingHorror
ch.Execute("delete from #tablename", table)
Problem
As we know, SharePoint saves data in database in plain text. Some fields even have concatenated strings like <id>;#<value> for user fields. Percents are saved as doubles (1.00000000000000 for 100%) and etc.
Ofcourse, I want to display data as they are displayed in lists.
What should I do?
Should I use derived SPBoundField to format values (Which I actually did and it works fine until you want to filter (probably SPBoundField won't format me values because i use ObjectDataSource not list and with reflector I saw if there are SPListItems in datasource, then it formats correctly. Not my case)
alt text http://img199.imageshack.us/img199/2797/ss20090820110331.png
Or must I loop through all the DataTable and format each row accordingly?
What are Your techniques?
Thank you.
Here is how I solved this issue.
<asp:TemplateField HeaderText="Campaign Members">
<ItemTemplate>
<%# RemoveCharacters(Eval("CampaignMembers").ToString())%>
</ItemTemplate>
</asp:TemplateField>
// Make sure declare using System.Text.RegularExpression;
protected string RemoveCharacters(object String)
{
string s1 = String.ToString();
string newString = Regex.Replace(s1, #"#[\d-];", string.Empty);
newString = Regex.Replace(newString, "#", " ");
return newString.ToString();
}
I normaly use ItemTemplates that inherit from ITemplate. With in the ItemTemplate I use the SPFieldxxxValue classes or some custom formating code. This saves looping through the DataTable and the ItemTemplates can be reused.
The ItemTemplates are attached in Column Binding
E.G
// Normal Data Binding
SPBoundField fld = new SPBoundField();
fld.HeaderText = field.DisplayName;
fld.DataField = field.InternalName;
fld.SortExpression = field.InternalName;
grid.Columns.Add(fld);
// ItemTemplate Binding
TemplateField fld = new TemplateField();
fld.HeaderText = field.DisplayName;
fld.ItemTemplate = new CustomItemTemplateClass(field.InternalName);
fld.SortExpression = field.InternalName;
grid.Columns.Add(fld);
An example of a ItemTemplate
public class CustomItemTemplateClass : ITemplate
{
private string FieldName
{ get; set; }
public CustomItemTemplateClass(string fieldName, string formatString)
{
FieldName = fieldName;
}
#region ITemplate Members
public void InstantiateIn(Control container)
{
Literal lit = new Literal();
lit.DataBinding += new EventHandler(lit_DataBinding);
container.Controls.Add(lit);
}
#endregion
void lit_DataBinding(object sender, EventArgs e)
{
Literal lit = (Literal)sender;
SPGridViewRow container = (SPGridViewRow)lit.NamingContainer;
string fieldValue = ((DataRowView)container.DataItem)[FieldName].ToString();
//Prosses Filed value here
SPFieldLookupValue lookupValue = new SPFieldLookupValue(fieldValue);
//Display new value
lit.Text = lookupValue.LookupValue;
}
}
Here are a few options. I don't know the output of all of them (would be a good blog post) but one of them should do what you want:
SPListItem.GetFormattedValue()
SPField.GetFieldValue()
SPField.GetFieldValueAsHtml()
SPField.GetFieldValueAsText()
It may also be handy to know that if you ever want to make use of the raw values then have a look at the SPField*XYZ*Value classes. For example the form <id>;#<value> you mention is represented by the class SPFieldUserValue. You can pass the raw text to its constructor and extract the ID, value, and most usefully User very easily.
I would suggest either to format the values before binding them to the spgridview. Linq and an anonymous type is preffered or to call a code behind function on the field that needs the formatting upon binding.
DataField='<%# FormatUserField(Eval("UserFieldName")) %>'
or...maybe a templated field?
After all, i did have not know any other solution to loop through DataTable rows and format them accordingly.
If your SPGridView's data source is list, try out SPBoundField.