I am trying to do following assert
Assert.AreEqual<string>(A.Drivers[i].FirstName, Response);
Drivers is IEnumerable collection and it has other properties like last name , middle name etc. I'd like to dynamically select the properties of Drivers so it can be done in one method rather than writing different methods for each property
You could do it using reflexion:
get string properties of the Drivers class
var driverProperties = typeof(Drivers).GetProperties().Where(i => i.PropertyType.Equals(typeof(string)));
and then iterate through the properties
foreach (var property in driverProperties)
{
Assert.AreEqual<string>(property.GetValue(A.Drivers[i]), Response);
}
slight change to Dano suggestion. To get one specific property
var prop = typeof(Drivers).GetProperty("propName");
var val = (string)prop.GetValue(A.Drivers[i]);
Related
I am creating a list like following:
var result = data.Select(p => new
{
p.FirstName,
p.LastName,
Relationship = p.RelationshipType,
p.TierType,
Gender = p.GenderType,
p.AnnualSalary
});
However, I need to add more properties into each of the array item of result like following
foreach(var property in ListOfAdditionalProperties)
{
// Add property logic
}
Is this possible?
I tried ExpandoObject but was not able to come up with the final result list that I get with the Lambda mentioned on top.
No, it's not possible.
You cannot add more members to a dynamic type after the type has been created.
Think of it as a class declaration. Once the class is declared and compiled it cannot be modified.
You need to use another approach, just like the ones you mention. But yes, that has it's drawbacks in regards to syntax.
I'm using TweetInvi to grab a bunch of tweets that match a specified hashtag. I do this with the following:
var matchingTweets = Search.SearchTweets(hashtag);
This returns an IEnumerable (named ITweet, interface of Tweet), however I cannot create a List<> of Tweets, because Tweet is a static type.
I made, instead, a list of objects, using:
List<object> matches = matchingTweets.Cast<object>().ToList();
However, although each member of the matchingTweets IEnumerable has a number of properties, I cannot access them using:
long tweetID = matches[i].<property>;
Using matches[i].ToString() returns the tweet content, so how can I effectively cast the results in matchingTweets to a list, and subsequently access the properties of those list members? I would ideally like to avoid using dynamic.
In your example above you were trying to grab the ID from the tweet. ITweet implements ITweetIdentifier which contains the Id property. You can literally just access it by:
var matchingTweets = Search.SearchTweets(hashtag);
//Grab the first 5 tweets from the results.
var firstFiveTweets = matchingTweets.Take(5).ToList();
//if you only want the ids and not the entire object
var firstFiveTweetIds = matchingTweets.Take(5).Select(t => t.Id).ToList();
//Iterate through and do stuff
foreach (var tweet in matchingTweets)
{
//These are just examples of the properties accessible to you...
if(tweet.Favorited)
{
var text = tweet.FullText;
}
if(tweet.RetweetCount > 100)
{
//TODO: Handle popular tweets...
}
}
//Get item at specific index
matchingTweets.ElementAt(index);
I don't know exactly what you want to do with all the info, but since the SearchTweets returns a IEnumerable of ITweets you have access to anything an ITweet has defined.
I highly recommend looking through their wiki. It's pretty well organized and gives you clear examples of some basic tasks.
It makes sense you cannot access the properties. You cast it into object so you can only access the objects properties and methods (that like you said might have been overridden).
It should be fine to just access it like this:
List<ITweet> tweets = matchingTweets.Take(5).ToList();
What you can do is project it to a new object of yours:
var tweets = matchingTweets.Select(item => new {
property1 = item.property1,
property2 = item.property2
})
.Take(5).ToList();
Then you will be able to access what you need. Now, if you need to share this data outside the scope of that function create a DTO object and initialize it instead of the anonymous type.
Depending on the size of the project and amount of effort usually it is in any case a good practice to create a layer of DTO objects when you interact with an external service like this. Then if their models changed you can contain your changes only to the DTOs.
If all you want are the ids of the first 5 then:
var ids = matchingTweets.Take(5).Select(item => item.id).ToList();
I have a single instance of an object:
AS_SYSTEM system = ctx.AS_SYSTEM.Where(s => s.SYSTEM_ID == query).First();
And i want to remove some properties from it. All properties that ends with "Reference". Something like
system.GetType().GetProperties().Name.EndsWith("Reference")
I want to remove all ef properties that are linked to other tables.
To nullify (the values) of all properties ending with 'Reference', using reflection:
var properties = system.GetType().GetProperties().Where(x => x.Name.EndsWith("Reference"));
foreach (var p in properties)
{
p.SetValue(system, null, null);
}
Though I'm not sure that you really need to use reflection here, thats how its done.
I'm OK with both C# and VB.NET
I have a function GetListOfBook, that returns LINQ to SQL result that has a collection of objects like the following:
var result = GetListOfBook();
Book is a Book object that property
of Title and ISBN,
Category is a string
Author is an Author object that has
Name and ID property.
So inside the collecton, it looks like this:
So inside the "result" collection it looks like this:
{Book = {Book}, Category = "English", Author = {Author}}
{Book = {Book}, Category = "English", Author = {Author}}
{Book = {Book}, Category = "Web Development", Author = {Author}}
I want to iterate over each item in the collection to get the Book title and ISBN, Category and the author name. Something like this:
foreach (var r in result)
{
Respone.Write(r.Book.Title, r.Book.ISBN, r.Category, r.Auhtor.Name);
}
At the moment, I cannot iterate over the collection yet. Thank you for any suggestion.
Update:
Sorry for the trouble. This is actually working. I found the typo in the code.
You still need to use the correct syntax for foreach which requires you to specify a type for the loop variable. Since you can't name it explicitly, you need to use var which infers the type.
foreach (var r in result)
{
Respone.Write(r.Book.Title, r.Book.ISBN, r.Category, r.Auhtor.Name);
}
You need to use an implicitly typed variable using var for the iteration variable within foreach, just as you presumably have for your query to start with:
var result = ...; // Your existing query
// r is implicitly typed here
foreach (var r in result)
{
Response.Write(r.Book.Title, r.Book.ISBN, r.Category, r.Author.Name);
}
EDIT: Looking more closely at your code, I suspect this is the problem:
var result = GetListOfBook();
This can't be strongly typed, if it's returning an anonymous type... which means it must be returning something like IEnumerable or IEnumerable<object>. I suspect you'll need to create an appropriate "normal" type to contain the results from GetListOfBook - or perform the query in the same method that does the Response.Write call.
you can use reflection like this:
foreach (var r in result)
{
PropertyInfo info = r.GetProperty("Category");
Response.Write(info.GetValue(r, null));
}
You can use reflection to access the anonymous type's properties.
You can see some samples here:
http://blogs.msdn.com/b/wriju/archive/2007/10/26/c-3-0-anonymous-type-and-net-reflection-hand-in-hand.aspx
But you should do it really as a last resort if you MUST use anonymous types rather than explicit types.
Is there a way to add a property to the objects of a Linq query result other than the following?
var query = from x in db.Courses
select new
{
x.OldProperty1,
x.OldProperty2,
x.OldProperty3,
NewProperty = true
};
I want to do this without listing out all of the current properties of my object. There are many properties, and I don't want to have to update this code whenever I may change my class.
I am still learning with LINQ and I appreciate your suggestions.
Add it with partial classes:
public partial class Courses
{
public String NewProperty { get; set; }
}
Then you can assign it after you've created the object.
I suppose you could return a new object composed of the new property and the selected object, like this:
var query = from x in db.Courses
select new
{
Course = x,
NewProperty = true
};
eking's answer will be the most straightforward approach.
If that doesn't work for you (because you need to pass the results around or whatever), and assuming the class you're dealing with already defines the property you want to set, you could create a copy constructor or factory method that takes an existing instance plus the value of the property you want to set:
var query = from x in db.Courses
select new Course(x, valueOfNewProperty);
Alternatively, if Course doesn't define the property, you could subclass it and use the same approach:
var query = from x in db.Courses
select new CourseWithExtraProperty(x, valueOfNewProperty);
(obviously, pick a better name for your subclass)
Again, though, unless you really need to do this, stick with eking's solution.
ServiceStack has a built-in way to handle this with the PopulateWith method.
Here's a code example.
foreach (var item in results)
{
var test1 = new ItemDto().PopulateWith(item);
test1.extraField1 = "extra";
response.Add(test1);
}`
And if you're not using ServiceStack, you can always use AutoMapper.
CreateMap<Foo, Bar>().ForMember(x => x.ExtraBarProperty, opt => opt.Ignore());
If you are looking to dynamically add a property to an object this could be a solution.
This is what has worked for me, I also had a concern and it was what happened with those domain objects that had many properties, the maintainability for any changes in the object was absurd, I managed to build an implementation with LINQ - ExpandObject - Reflection, which helped to keep my object dynamic and only add the additional properties that my view logic required.
var expandedModel = db.Courses.Select(x =>
{
dynamic expandObject = new ExpandoObject();
expandObject.NewProperty= $"PropertyValue";
foreach (var property in x.GetType().GetProperties())
{
((IDictionary<string, object>)expandObject).Add(property.Name, property.GetValue(x));
}
return expandObject;
}).ToList();