I have this class
class UserData
{
public UserData() { }
public string Name { get; set; }
public string Val { get; set; }
}
I have a normal ListBox. Im selecting Data from MySql.
private void ListUsers(string server)
{
List<UserData> ls = new List<UserData>();
foreach(dynamic obj in _data)
{
if(obj.servername == server)
{
ls.Add(new UserData() { Name = obj.username, Val = obj.password });
}
}
UserList.Sorted = true;
UserList.DisplayMember = "Name";
UserList.ValueMember = "Val";
UserList.DataSource = ls;
}
When debugging the ls it contains
[0]
Name => "Test",
Val => "12345"
[1]
Name => "Test2",
Val => "54321"
Now sometimes there ist only 1 postition in that list. If this happens, I want to select that entry or at least the Name and paste this into a textbox.
But for some reason I cant achive this. And Google didnt brought any results. At least non that suites to my problem.
I tried
rdpUserList.Items[0].ToString();
but this brings me ProjectName.UserData and not Test.
What is the right way to select the first Item in a list that was generated by a datasource ?
You're calling ToString() on an instance of the type ProjectName.UserData, which gives you its type name.
You want to access that instance's Name property instead.
If rdpUserList is a List<UserData>, you want this:
rdpUserList.Items[0].Name
If instead it's a datasource, you need to cast the item in order to access its properties:
((ProjectName.UserData)rdpUserList.Items[0]).Name
There are two approaches to this issue. The first is a logical problem; you need to call the Name property and not the ToString() method. Note that using this way, you need to cast to your object type.
((UserData)rdpUserList.Items[0]).Name
The second option is to override the ToString() method so you can call the name the way you tried.
class UserData
{
public UserData() { }
public string Name { get; set; }
public string Val { get; set; }
public override string ToString()
{ return this.Name; }
}
and then call with
rdpUserList.Items[0].ToString()
Sorry for previous post, I did not test before I answered,
try the following if you want, I just like linq :)
var item = rdpUserList.Items.OfType<ListItem>().First();
Class1 t = new Class1(){Id=Convert.ToInt32(item.Value), description = item.Text};
OR for just the name
string name = rdpUserList.Items.OfType<ListItem>().First().Text;
Related
I want to pass C# object as query string & i used following code to get the desired result.
class Program
{
public static string GetQueryString(object obj)
{
var properties = from p in obj.GetType().GetProperties()
where p.GetValue(obj, null) != null
select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(obj, null).ToString());
return String.Join("&", properties.ToArray());
}
static void Main(string[] args)
{
Filters fil = new Filters();
fil.Age = 10;
fil.Id = "some id";
fil.Divisions = new List<string>();
fil.Divisions.Add("div 1");
fil.Divisions.Add("div 2");
fil.Divisions.Add("div 3");
fil.Names = new List<string>();
fil.Names.Add("name 1");
fil.Names.Add("name 2");
fil.Names.Add("name 3");
var queryStr = GetQueryString(fil);
Console.ReadKey();
}
}
public class Filters
{
public List<string> Names { get; set; }
public List<string> Divisions { get; set; }
public int Age { get; set; }
public string Id { get; set; }
}
using the above code give me following result:
Names=System.Collections.Generic.List%601%5bSystem.String%5d&Divisions=System.Collections.Generic.List%601%5bSystem.String%5d&Age=10&Id=some+id
The output is not a valid query string. I need help to convert any POCO class into query string format.
I have a similar JavaScript object and i am able to convert it into correct query string.
{
"id":"some id",
"age":10,
"division":["div 1","div 2","div 3"],
"names":["name 1","name 2","name 3"]
}
using Jquery I can say $.param(obj) and this will result in:
"id=some+id&age=10&division%5B%5D=div+1&division%5B%5D=div+2&division%5B%5D=div+3&names%5B%5D=name+1&names%5B%5D=name+2&names%5B%5D=name+3"
I want a similar output using c#.
It looks like The problem is that you are calling ToString() on your objects. List<String>.ToString() will return "List<System.String>", which is what you're seeing, except URL encoded.
You will need to either:
Provide an iterface with a ToQueryString method:
public interface IQueryStringable
{
string ToQueryString();
}
and have all classes you might want to use as query strings implement it, or
Rewrite your reflection so that it iterates sequences. Something like (pseudocode):
Get property.
See if it is an instance of IEnumerable. If not, proceed as before
Otherwise:
for each item, construct a string consisting of the property name, "[]=" and the value of that item.
Concatenate the produced strings and urlencode it.
For sanity's sake, I would recommend option 1, and I enjoy playing with reflection. It gets more complex if you want to allow arbitrary nesting of classes.
here is code illustration
interface IObjectA
{
int Id { get; }
string Name { get; }
}
class ObjectA : IObjectA
{
public int Id { get; set; }
public string Name { get; set; }
public ObjectA(int id, string name)
{
Id = id;
Name = name;
}
}
There are two ways for me to generate List<IObjectA> from some other objects
First one is using forloop:
IList<IObjectA> list = new List<IObjectA>();
foreach(var item in someList)
{
list.Add(new ObjectA(item.Id, item.Name));
}
This works perfectly fine.
Then I tried with linq
IList<IObjectA> list = someList.Select(c => new ObjectA(c.Id, c.Name)).ToList();
The compiler will throw me a error basically saying cannot convert ObjectA to IObjectA
To make it work, i have to add
IList<IObjectA> list = someList.Select(c => new ObjectA(c.Id, c.Name)).Cast<IObjectA>().ToList();
Can some one explain why the compile would complain?
Thanks in advance!
The problem is that the linq expressions result in a List<ObjectA>. If you can treat this result as a List<IObjectA>, the compiler might let you add hypothetical OtherObjectA objects to the list, which would blow up on you if you ever tried to cast back to the original List<ObjectA> type, which should be allowed.
To get around this, you can .Cast() the elements before calling .ToList() to get a list of the correct type:
IList<IObjectA> list = someList.Select(c => new ObjectA(c.Id, c.Name)).Cast<IObjectA>().ToList();
You could also use the var keyword:
var list = someList.Select(c => new ObjectA(c.Id, c.Name)).ToList();
But this will still result in a List<ObjectA> and I suspect you need the List<IObjectA> for code further on.
I have a Dictionary<string, object> which holds a property name as string and it's value as object. I also have a Bind method extension which, through reflection, sets that propery name with its corresponding value:
public static T Bind<T>(this T #this,
Dictionary<string, object> newValues,
params string[] exceptions) where T : class
{
var sourceType = #this.GetType();
foreach (var pair in newValues.Where(v => !exceptions.Contains(v.Key)))
{
var property = sourceType.GetProperty(pair.Key,
BindingFlags.SetProperty |
BindingFlags.Public |
BindingFlags.Instance);
var propType = Nullable.GetUnderlyingType(property.PropertyType) ??
property.PropertyType;
property.SetValue(#this, (pair.Value == null) ? null :
Convert.ChangeType(pair.Value, propType), null);
}
return #this;
}
For instance, consider a class like this:
public class User
{
public string Name { get; set; }
public DateTime Date { get; set; }
}
Everything runs fine, except when I got a class with a property name of another object, like this:
public class User
{
public string Name { get; set; }
public DateTime Date { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string PostalCode { get; set; }
}
So, if I try to send a Name property name, ok, but I got problems with composite property names, like Address.PostalCode.
Can you advise a way to handle that situation?
EDIT #1:
To summarize the problem: calling sourceType.GetProperty("Name", ...) in the context of a User class instance correctly allows to set its value, but it doesn't work using a sourceType.GetProperty("Address.PostalCode", ...) in same instance.
EDIT #2:
A more complete example should be:
var user = new User{ Address = new Address() };
var values = new Dictionary<string, object>
{
{ "Name" , "Sample" },
{ "Date" , DateTime.Today },
{ "Address.PostalCode", "12345" } // Here lies the problem
}
user.Bind(values);
My guess is that Convert.ChangeType only works for objects implementing IConvertible. Thus, I'd just add a check, and only use Convert.ChangeType if pair.Value has a type that implements IConvertible. Furthermore, afaik Convert does not use overloaded conversion operators, so you can save this check whenever pair.Value is not a struct, i.e.
object value;
if (pair.Value == null) {
value = null;
} else {
value = pair.Value.GetType().IsStruct ? Convert.ChangeType(pair.Value, propType) : pair.Value;
}
...
There are many binding engines out there, WPF, ASP.NET MVC, winforms in the core .NET and who knows how many others, you can check out all their source codes and documentation about their syntax.
Let's see the most simple case. Let's say that the variable X holds an object and you have the binding expression "A.B.C". Let's split up the binding path, the first part is "A". So you use reflection to get the property named "A" in X, and you put that other object into X. Now comes the second part, "B", so let's find a property named "B" in (the new) X. You find that, and put that into X. Now you get to the final part, "C", and now you can either read or write that property in X. The point is that you don't need recursion or anything, it's just a simple loop, you iterate over the parts of the binding expression, evaluate them, and you keep the current object in the same variable.
But the fact is that it can get much more complex than that. You could ask for array indexing, like "A.B[2].C". Or what if you have a path "A.B", and X.A is null, what do you do? Instantiate X.A, but what if it lacks a public parameterless constructor?
I want you to see that it can be a very complex problem. You have to specify a syntax and rules, and then implement that. You didn't specify in your question the exact syntax and rules you want to use. And if it happens to be more than the simple case I mentioned above, then the solution could be too lengthy.
I was able to solve it identifying if the property name have a period and recurring it:
public static T Bind<T>(this T #this,
Dictionary<string, object> newValues,
params string[] exceptions) where T : class
{
var sourceType = #this.GetType();
var binding = BindingFlags.Public | BindingFlags.Instance;
foreach (var pair in newValues.Where(v => !exceptions.Contains(v.Key)))
{
if(pair.Key.Contains("."))
{
var property = sourceType.GetProperty(
pair.Key.Split('.').First(),
binding | BindingFlags.GetProperty);
var value = property.GetValue(#this, null);
value.Bind(new Dictionary<string, object>
{
{
String.Join(".", pair.Key.Split('.').Skip(1).ToArray()),
pair.Value
}
});
}
else
{
var property = sourceType.GetProperty(pair.Key,
binding | BindingFlags.SetProperty);
var propType = Nullable.GetUnderlyingType(property.PropertyType) ??
property.PropertyType;
property.SetValue(#this, (pair.Value == null) ? null :
Convert.ChangeType(pair.Value, propType), null);
}
}
return #this;
}
Usage:
var user = new User {Address = new Address{ User = new User() }};
var values = new Dictionary<string, object>()
{
{"Name", "Sample"},
{"Date", DateTime.Today},
{"Address.PostalCode", "12345"},
{"Address.User.Name", "Sub Sample"}
};
user.Bind(values);
public class User
{
public string Name { get; set; }
public DateTime Date { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string PostalCode { get; set; }
public User User { get; set; }
}
I have a class called say
Class1
public string store { get; set; }
What I want is to decorate it with something like this;
Class1
[GetStoreNumberFromName]
[IsNumeric]
public string store {get; set; }
So the value might be 1234, or it might be 1234 - Store name
What I need to do is check to see if the value passed has only numbers in it. If it doesn't then I need, in the second example, to grab the first 4 chrs and change the value of the property to that.
So if the passed in value was 1234 - Store Name then at the end of [GetStoreNumberFromName] the value of store should be 1234 so that [IsNumeric] will pass as valid.
Okay.. hopefully I've understood your requirement:
class GetStoreNumberFromNameAttribute : Attribute {
}
class Class1 {
[GetStoreNumberFromName]
public string store { get; set; }
}
class Validator<T>
{
public bool IsValid(T obj)
{
var propertiesWithAttribute = typeof(T)
.GetProperties()
.Where(x => Attribute.IsDefined(x, typeof(GetStoreNumberFromNameAttribute)));
foreach (var property in propertiesWithAttribute)
{
if (!Regex.Match(property.GetValue(obj).ToString(), #"^\d+$").Success)
{
property.SetValue(obj, Regex.Match(property.GetValue(obj).ToString(), #"\d+").Groups[0].Value);
}
}
return true;
}
}
..usage:
var obj = new Class1() { store = "1234 - Test" };
Validator<Class1> validator = new Validator<Class1>();
validator.IsValid(obj);
Console.WriteLine(obj.store); // prints "1234"
..obviously needs some changes on your end.. but it should give you an idea (I'm aware that the method naming probably isn't the best.. :/)
If I've missed the point entirely let me know and I'll delete.
I would like to automatically generate SQL statements from a class instance. The method should look like Update(object[] Properties, object PrimaryKeyProperty). The method is part of an instance (class, base method - generic for any child). Array of properties is an array of class properties, that will be used in update statement. Property names are equal to table field names.
The problem is that I can't get property names.
Is there any option to get a property name inside class instance?
sample:
public class MyClass {
public int iMyProperty { get; set; }
public string cMyProperty2 { get; set; }
{
main() {
MyClass _main = new MyClass();
_main.iMyProperty.*PropertyName* // should return string "iMyProperty"
{
I am aware of PropertyInfo, but I don't know hot to get the ID of a property from GetProperties() array.
Any suggestion?
Just wrote an implementation of this for a presentation on lambdas for our usergroup last Tuesday.
You can do
MembersOf<Animal>.GetName(x => x.Status)
Or
var a = new Animal()
a.MemberName(x => x.Status)
the code:
public static class MembersOf<T> {
public static string GetName<R>(Expression<Func<T,R>> expr) {
var node = expr.Body as MemberExpression;
if (object.ReferenceEquals(null, node))
throw new InvalidOperationException("Expression must be of member access");
return node.Member.Name;
}
}
Link to the presentation and code samples.
Also in SVN (more likely to be updated): http://gim-projects.googlecode.com/svn/presentations/CantDanceTheLambda
I found a perfect solution in This Post
public static string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
{
return (propertyExpression.Body as MemberExpression).Member.Name;
}
And then for the usage :
var propertyName = GetPropertyName(
() => myObject.AProperty); // returns "AProperty"
Works like a charm
You can do something like this:
Type t = someInstance.getType();
foreach (MemberInfo mi in t.GetMembers())
{
if (mi.MemberType == MemberTypes.Property)
{
Console.WriteLine(mi.Name);
}
}
to get all the property names for instance's type.
You can get the name (I assume that's what you meant by ID) of a property using PropertyInfo.Name. Just loop through the PropertyInfo[] returned from typeof(className).GetProperties()
foreach (PropertyInfo info in typeof(MyClass).GetProperties())
{
string name = info.Name;
// use name here
}
Since you already have an explicit handle to the specific property you want, you know the name - can you just type it?
Not 100% sure if this will get you what you're looking for, this will fetch all properties with [Column] attribute inside your class:
In the datacontext I have:
public ReadOnlyCollection<MetaDataMember> ColumnNames<TEntity>( )
{
return this.Mapping.MappingSource.GetModel(typeof(DataContext)).GetMetaType(typeof(TEntity)).DataMembers;
}
Fetching the table column-names that are properties inside the class:
MyDataContext db = GetDataContext();
var allColumnPropertyNames = db.ColumnNames<Animal>().Where(n => n.Member.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false).FirstOrDefault() != null).Select(n => n.Name);
Let's say (from the first sample, method update of a class MyClass):
public class MyClass {
public int iMyStatusProperty { get; set; }
public int iMyKey { get; set; }
public int UpdateStatusProperty(int iValue){
this.iMyStatusProperty = iValue;
return _Update( new[iMyStatusProperty ], iMyKey); // this should generate SQL: "UPDATE MyClass set iMyStatusProperty = {iMyStatusProperty} where iMyKey = {iMyKey}"
}
{iMyStatusProperty} and {iMyKey} are property values of a class instance.
So, the problem is how to get property name (reflection) from a property without using names of properties as strings (to avoid field name typos).