I have an object User:
public class User
{
public String Name { get; set; }
public String Name2 { get; set; }
public String Name3 { get; set; }
}
Also I have a Key Value set of strings that I want to assign to the object's properties when I create it:
'Name':'srgrgsdfsdf'
'Name3':'dsfdsfafafd'
'Name2':'dtewtwerwer'
'Name4':'546353452552'
Now I create my object like this
User user = new User();
user.Name = "zzxasdas";
The problem is that I want to be able to assign the Key/Value data dynamically. This means that some of the items can be missing or the order may be different.
How can I check the name of the object properties dynamically and compare it with the Key like this:?
foreach [key] in Key/Value
if [user] has property named [key]
add [value] to [user] property with the name [key]
You would need to use Reflection to do this.
In particular, Type.GetProperties or Type.GetProperty will allow you to discover information about the properties defined on a type, and get or set their values.
This might look something like:
User user = new User();
Type t = user.GetType();
foreach(var kvp in propertyDictionary)
{
var prop = t.GetProperty(kvp.Key);
if (prop != null)
prop.SetValue(user, kvp.Value);
}
There are two things that comes to my mind.
One is obviously using Reflection APIs. For example, if user.GetType().GetProperty() etc.
Second, there might be a chance that AutoMapper is a solution for you which copies property from one object to another with same name
Related
I have a database table in SQL Server and I need to configure a .NET application to use some of the data in this table, this data is used in a SOAP API call.
For example, the table has these columns
FirstName | LastName | EmailAddress
The values in these columns need to map to certain fields in the API call. This configuration must be flexible, so I cannot just assign FirstName to apiobject.firstname, for example.
Is there a way to derive a string to a property of an object?
For example, for FirstName, would it be possible to resolve it to object.Firstname = value but not doing it like this
if(column == "FirstName")
{
ApiObject.FirstName = columnValue
}
Rather I would want to do something like
ApiObject.[somehow-resolve-which-field] = columnValue
Does anyone know what I am on about?
If you does not have notation of this class and you simply want to create an object with required properties - the right way is to use dynamic, as it noted in other answers.
If you already have a class, for example:
public class MyClass
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
}
You can do what you want with reflection as following:
var myObject = new MyClass();
var prop = myObject.GetType().GetProperty(column);
prop.SetValue(myObject, columnValue);
Where column and columnValue are from your example. Note that column should be of string type and columnValue should match the type of property.
If I correctly understood you need an object which you don't know how many properties have it and what are these properties. For this situations there is dynamic keyword in c#. You can initialize your ApiObject as dynamic
dynamic ApiObject = new ExpandoObject();
then you can set properties of this object as following:
ApiObject.YourProperty=columnValue;
more details: About ExpandoObject
UPDATE
if you want to know which column is this, there is a ColumnName of DataTable of System.Data namespace. There are some issues for getting columns of table in c#. One of them is:
How do I get column names to print in this C# program?
I made a class for deserialize a JSON (I'm using JSON.net), this is the structure:
public class User
{
public string Name { get; set; }
public string Surname { get; set;}
}
public class RootObject
{
public List<User> Users { get; set; }
}
I deserialize the JSON like this:
var obj = JsonConvert.DeserializeObject<RootObject>(responseText);
Now If I want return all the JSON I simply do: return obj.Users; but how can I return a specific property of the class User? In particular the Name property. I tried this:
return obj.Users.name // user list does not contain any name property
Also I tried with LINQ:
obj.Select(c => c.Name).Single();
But I can't use Select because I need to declare obj as:
var obj = JsonConvert.DeserializeObject<List<RootObject>>(responseText);
If instead I return obj.user; I can use LINQ and access to the name. But how can do this in the method that return the response?
Add a reference to class
using System.Linq;
since user is of type List you can apply lambda expression in it. Do not use Single it will fail if user will have more than one record in it, use FirstOrDefault instead. It will work for zero or more number of elements
var obj = JsonConvert.DeserializeObject<RootObject>(responseText);
string name = obj.user.Select(p=> p.name).FirstOrDefault();
string surname = obj.user.Select(p=> p.surname).FirstOrDefault();
You have to use one user instead of the whole list as RootObject.user is a List<User> and not an instance of User:
var name = obj[0].Name;
Or whatever element within your list you want to use.
Alternativly use LINQ:
var user = obj.FirstOrDefault();
if (user != null) name = user.name;
I have a database which stores different locations. Based on the type of the location, the unique details are stored in a different table than the common properties (i.e. Name, Coordinates, Description are stored in the Locations table, while Population is stored in the CityDetails table).
The tables are connected via FK in the "specific details" table.
Since there are more than one "specific details" table I'm scratching my head how to query those multiple tables.
My Location object looks like this:
[Table("Locations")]
public class LocationData
{
public Guid Id { get; set; }
// multiple different properties here.
public string Type { get; set; }
public DetailsData { get; set; }
}
based on the Type property I can see which details table I have to query. A details table looks at least like this:
public abstract class DetailsData
{
[Key, ForeignKey("Location")]
public Guid { get; set; }
public LocationData Location { get; set; }
}
Every table that represents a location type then inherits from the DetailsData class and is configured to use the "Table-per-concrete-class" inheritance hierarchy.
Here is an example of what a "specific details" table might look like:
[Table("CityDetails")]
public class CityDetailsData : DetailsData
{
public string Planet { get; set; }
public int Population { get; set; }
}
How can I populate the DetailsData property in the Location class. Here is my current LINQ query:
from l in Locations
select new
{
Id = l.Id,
Name = l.Name,
Description = l.Description,
Coordinates = l.Coordinates,
Type = l.Type,
DetailsData = CityDetails // Here lies the problem. How can I populate this property properly?
}
Okay, I'm working on the assumption that your details tables all have different sets of columns, that you want to be able to use IEnumerable<LocationData> instances, and that you want to be able to directly access the properties of the instances of whatever details table object you return.
That's a toughie. There are basically three ways you can write code for an object of unknown type:
Give it a type of Object.
Make all "details" tables inherit from a common interface, and make CityDetails an object that implements that interface.
Use a generic type, which means you do ultimately specify the type, but you can push that decision up the chain to a declarer of your implemented type.
Using System.Object means that you either need to cast all your DetailsData objects to the required type (or use Reflection to access their properties), whereas using an interface means you can access some properties directly, but probably not everything you want.
I think a generic type might be your best, hybrid, solution.
I would do something like this:
Accept that there isn't a perfect solution.
Instead of creating an anonymous type, as you are doing in your example code, define a class like this (akin to a ViewModel, if you're using ASP.NET MVC):
public class LocationViewModel<TDetailsData>
{
public Guid Id { get; set; }
// multiple different properties here.
public string Type { get; set; }
public TDetailsData DetailsData { get; set; }
}
Define a helper method that takes a type parameter and returns a value of type TDetailsData. Use that to populate your DetailsData property on LocationViewModel.
TDetailsData GetLocationDetails<TDetailsData>(string type, Guid ID)
{
// get the appropriate data based on the type.
}
If you need to keep an IEnumerable of these objects, define an interface ILocationDataViewModel and another of ILocationDataViewModel<TDetailsData>, make LocationViewModel implement both of them, and use IEnumerable<ILocationDataViewModel> or IEnumerable<ILocationDataViewModel<CityDetailsData>>, etc., as called for by the situation.
If I understood correctly, you would like to dynamically determine the type and deal with it on the fly. In that case, you can go with dynamic. I have not tested this code, but you can think in that line
public DetailsData GetDetailsData(Type t)
{
dynamic typVal = new ExpandoObject();
if(t == typeof(CityDetails))
{
typVal = new CityDetails();
}
// add other types
return (DetailsData)PopulateDetailsData(typVal);
}
public DetailsData PopulateDetailsData(CityDetails cd)
{
cd.Planet = new CityDetails().Planet;
return cd;
}
// Add other type related methods with same
// signature with input parameter differentiated by types
// for example
public DetailsData PopulateDetailsData(TownDetails td)
{
td.Income = new TownDetails().Income;
return td;
}
in query, you can have something like below
from l in Locations
select new
{
Id = l.Id,
Name = l.Name,
Description = l.Description,
Coordinates = l.Coordinates,
Type = l.Type,
DetailsData = GetDetailsData(l.Type)
}
I have a class (Application) that has multiple properties of the type of another custom class (Employment). I would like to validate that Employment class conditionally based on whether the property of the Application class is marked with [Required].
From what I've found, I think I should be utilizing the IValidatableObject interface for Employment. The problem is that I'm not sure how to use reflection (or something else maybe) to check if this instance of the class is annotated with the [Required] attribute to determine whether to validate it or not.
Maybe this isn't even possible. I initially set up two classes for the Employment class: Employment and EmploymentRequired. Only the latter had the validation attributes on its properties. It works, but I'd like to just have one class to use if possible.
public class Application
{
[Required]
public Employment Employer1 { get; set; }
public Employment Employer2 { get; set; }
}
public class Employment : IValidatableObject
{
[Required]
public string EmployerName { get; set; }
[Required]
public string JobTitle { get; set; }
public string Phone { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
var t = this.GetType();
//var pi = t.GetProperty("Id");
//var isRequired = Attribute.IsDefined(pi, typeof(RequiredAttribute));
//how can I get the attributes of this property in Application class?
if (isRequired)
{
Validator.TryValidateProperty(this.EmployerName,
new ValidationContext(this, null, null) { MemberName = "EmployerName" }, results);
Validator.TryValidateProperty(this.JobTitle,
new ValidationContext(this, null, null) { MemberName = "JobTitle" }, results);
}
return results;
}
}
You should be able to check for the required attribute using Attribute.IsDefined.
http://msdn.microsoft.com/en-us/library/system.attribute.isdefined.aspx
Seems like you can't do this, because using reflection you can't get parent object/class that references your current instance and all the more so reference property information.
EDIT: Maybe you can make Employment type Generic with required and non required validation modes?
I think you are searching for the Attribute.IsDefined method. You would have to first obtain the reference to the field itself, and then validate the presence of the attribute. Like the following (adapted from the example at MSDN):
// Get the class type (you can also get it directly from an instance)
Type clsType = typeof(Application);
// Get the FieldInfo object
FieldInfo fInfo = clsType.GetField("Employer1");
// See if the Required attribute is defined for the field
bool isRequired = Attribute.IsDefined(fInfo , typeof(RequiredAttribute));
Since what I'm trying to do doesn't seem to be possible exactly, I found a different way to do it, based on the suggestion of #user1578874. I added an IsRequired property to Employment and used MVC Foolproof Validation to mark those properties as [RequiredIf("IsRequired")]. Seems to be the cleanest solution.
I have to export data to Excel programmatically. I have a class with several properties. I was wondering if it's possible to retrieve values of all properties using a loop. For instance:
public class SqueezeProperties
{
public int WidthField { get; set; }
public string Width_unit { get; set; }
public int ResPressure { get; set; }
public int DensityField { get; set; }
......
}
While writing to excel, I code as:
t = typeof(SqueezeProperties);
foreach (PropertyInfo field in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
oSheet.Cells[r, c++] = field.Name;
Now to input values, is there any way that I can iterate and find values of all properties that can be accessed, and store them in excel?
I doubt if it is even possible. I just taught myself how to access the property name & its details, so I thought maybe the other thing could also be possible and I am simply unaware of it.
Thanks
You can use PropertyInfo.GetValue.
(However according to specification the order of your properties is not guaranteed to be the same as the definition order. So to be safe you might want to order them.)
Also instead of getting them via reflection you could create a collection manually instead, this would take care of the order already.
e.g.
var properties = new Expression<Func<SqueezeProperties, object>>[]
{
o => o.WidthField,
o => o.Width_unit,
//...
};
foreach (var exp in properties)
{
var mem = (MemberExpression)exp.Body;
var prop = (PropertyInfo)mem.Member;
oSheet.Cells[r, c++] = prop.GetValue(squeezePropertiesInstance, null);
}