How do I create a view from a generic list? - c#

I have a generic list List<T> and I want to create a view that iterates the list and spits out the output.
I'm coming up against a couple of issues:
I don't know how to get my view.aspx to understand T
I don't know how to get it to render the correct partial for T
For instance, if I pass in a list of CustomObject1 then I want to render the partial CustomObject1.ascx and if I pass in a list of CustomObject2 the I want to render the partial CustomObject2.ascx.
Is there a simple way to do this that I've overlooked? I don't want to have a different aspx for every type of list I want to use, I'm just generating a of items after all. So it's a waste to have 15 different views to cover each type of list I'm going to need to use.
Any ideas or solutions would be gratefully received.

If your names are always going to match (CustomObject1 then I want to render the partial CustomObject1.ascx), then you could use the type name. So:
void MyMethod(List<T> items)
{
foreach(T item in items)
{
Html.RenderPartial(item.GetType().Name, item);
}
}

Example of Anthony's first answer: make the list contents responsible for rendering themselves by e.g.
interface IHtmlRenderable
{
void RenderHtml();
}
void MyMethod(List<T> items) //where T implements IHtmlRenderable
{
foreach(T item in items) ((IHtmlRenderable)item).RenderHtml();
}
But John's answer seems cleaner because you don't need to spend effort implementing this interface on each of your classes - or adding attributes etc.

Sounds to me that you first need to be using an Interface which is common to all your CustomObjects. Your View would then be base on List<IMyCommonInterface>.
As to including the correct ascx I'm not sure how even the generic system would solve this.
There are two approaches I can think of.
Have ICommonInterface expose a property that specifies the custom control to use. Simple but somehow feels all wrong and dirty.
Create an Attribute class that can be used to decorate the CustomObject classes, this attribute specifies the custom control to use. More complex because it requires a little reflection to discover the value of the attribute but somehow feels right and clean.

Related

Call class and method from two strings

I have a WPF application that has two combo boxes, one with what I'm calling a FileType and one with Actions (add, edit, delete, etc.). Every FileType has a corresponding class. What I'm trying to do is for example if FileTypeA is selected and the action is Add then I want to do something along these lines:
void myMethod(string FileType, string Action)
{
//using reflection find class from the FileType string, and call method Action
var x = new FileTypeA();
x.Add();
}
if the user selects FileTypeB and Delete then the object created and the method called will change accordingly. I think this might be possible using reflection, but I'm trying to find out if there is even a better way using perhaps a generic class? since all these FileType classes are very similar.
try to create an interface IFileType with basic methods Add,Delete,Save
Implement this interface on all fileTypes classes e.g DocFile,PdfFile etc.
Bind the List to ComboBox and use its selected Item object as cast it as IFileType and call its method via interface(Delete/Save) without doing any reflection.
I would recommend using MVVM pattern so that you can easily create separation of layer and have benefits of OOP.
If you aim to call a certain action for item according to the selected option from ComboBox, get familiar with delegates. Then use the approach of binding a collection of options (with the delegate included) to ComboBox

create generic mvc view in mvc4

I have raised similar question before, have got no answers.
How can I create a generic mvc4 view that can display list of or a single model that is passed to it. model can be either Person or Organization or Party whatever that is passed to it.
If you are looking for something like:
#model MyViewModel<T> where T : IViewModel
... then that is not supported by Razor.
You may be able to use something like this:
#model MyViewModel<IViewModel>
... that way you could define all types that could be passed as follows
public class Person : IViewModel { ... }
public class Organisation : IViewModel { ... }
public class Party : IViewModel { ... }
Please, DON'T DO THAT!!
You should make a view for each kind of object / list of objects.
However, yu can still reuse elements:
keep the common part (menu, header, footer...) on the site layout
make a view for each kind of object
make a view for each kind of list. in this vie you can use the object's view as a partial view and render it as many times as object are on the list.
Another possibility is to make templates for "Display For" for each kind of object. You can define a view for each kind of object, and store it in an special folder. When you use Html.Display or Html.DisplayForin your templates, the system will choose and render the right template depending on the type of the object to display. (You could also make named templates, and select them by name). For an introduction on this technique, look at this excellent posts by Brad Wilson.
But I insist, please, don't make a "generic view", as this will add extra complexity (check if it's a list or a simple object, get the type of the object, choose how to display it and display it). You can make very simple views by reusing the elements as explained, and letting the controllers decide which view to show for each object or list of object. Or use templates. In this way your system will be easier to maintain and less prone to errors because of added complexity (you don't need to change the same template all the time, but to add new templates, with very few code on them)
What I can't understand is why you want to have a simple view. What's the reason for it?
#model MyViewModel<IViewModel>
If you define a model like this then this error occurs:
Server Error in '/' Application.
The model item passed into the dictionary is of type MyViewModel\'1[Person], but this dictionary requires a model item of type MyViewModel'1[IViewModel].
To achieve a Generic View Use below code. dynamic is an inbuilt keyword that accepts any model.It worked fine for me
#model dynamic
or
#model IEnumerable<dynamic>

Using Generics to accomplish an HTML scraper. Right or Wrong?

My requirement is to download and scrape various HTML pages, extracting lists of Objects from the code on the page depending on what object type we are looking for on that page. Eg one page might contain an embedded list of doctors surgeries, another might contain a list of primary trusts etc. I have to view the pages one by one and end up with lists of the appropriate object types.
The way I have chosen to do this is to have a Generic class called HTMLParser<T> where T : IEntity, new()
IEntity is the interface that all the object types that can be scraped will implement, though I haven't figured out yet what the interface members will be.
So you will effectively be able to say
HTMLParser<Surgery> parser = new HTMLParser<Surgery>(URL, XSD SCHEMA DOC);
IList<Surgery> results = parser.Parse();
Parse() will validate that the HTML string downloaded from the URL contains a block that conforms to the XSD document provided, then will somehow use this template to extract a List<Surgery> of Surgery objects, each one corresponding to an XML block in the HTML string.
The problems I have are
Im not sure how to specify the template for each object type in a nice way, other than HTMLParser<Surgery> parser = new HTMLParser<Surgery>(new URI("...."), Surgery.Template); which is a bit clunky. Can anyone suggest a better way using .NET 3.0/4.0?
Im not sure how in a Generic way I can take the HTML string, take an XSD or XML template document, and return a generic list of constructed objects of the Generic Type. Can anyone suggest on how to do this?
Finally, I'm not convinced generics are the right solution to this problem as it's starting to seem very convoluted. Would you agree with or condemn my choice of solution here and if not, what would you do instead?
I'm not convinced that generics are the right solution, either. I implemented something very similar to this using good old inheritance, and I still think that's the right tool for the job.
Generics are useful when you want to perform the same operations on different types. Collections, for example, are a good example of where generics are very handy.
Inheritance, on the other hand, is useful when you want an object to inherit common functionality, but then extend and/or modify that functionality. Doing that with generics is messy.
My scraper base class looks something like this:
public class ScraperBase
{
// Common methods for making web requests, etc.
// When you want to download and scrape a page, you call this:
public List<string> DownloadAndScrape(string url)
{
// make request and download page.
// Then call Scrape ...
return Scrape(pageText);
}
// And an abstract Scrape method that returns a List<string>
// Inheritors implement this method.
public abstract List<string> Scrape(string pageText);
}
There's some other stuff in there for logging, error reporting, etc., but that's the gist of it.
Now, let's say I have a Wordpress blog scraper:
public class WordpressBlogScraper : ScraperBase
{
// just implement the Scrape method
public override List<string> Scrape(string pageText)
{
// do Wordpress-specific parsing and return data.
}
}
And I can do the same thing to write a Blogspot scraper, or a custom scraper for any page, site, or class of data.
I actually tried to do something similar, but rather than using inheritance I used a scraper callback function. Something like:
public delegate List<string> PageScraperDelegate(string pageText);
public class PageScraper
{
public List<string> DownloadAndScrape(string url, PageScraperDelegate callback)
{
// download data to pageText;
return callback(pageText);
}
}
You can then write:
var myScraper = new PageScraper();
myScraper.DownloadAndScrape("http://example.com/index.html", ScrapeExample);
private List<string> ScrapeExample(string pageText)
{
// do the scraping here and return a List<string>
}
That works reasonably well, and eliminates having to create a new class for every scraper type. However, I found that in my situation it was too limiting. I ended up needing a different class for almost every type of scraper, so I just went ahead and used inheritance.
I would rather focus on your parser/verifier classes, as designing them properly will be cruicial to the ease of future usage. I think it's more important how the mechanism will determine which parser/verifier to use basing on input.
Also, what happens when you're told you need to parse yet another type of website, say for Invoiceentities - will you be able to extend your mechanism in 2 easy steps in order to handle such requirement?

Architectural question regarding Interfaces implementation and extensibility

I've created a sample app, just to test and try out some of wpf's capabilities. I was basically trying out the databinding in wpf, and did the rest of stuff more or less quickly. THen, i faced an arquitectural problem (yes, should have thought in advance before starting coding :) ) and i wanted to know what's the best refactoring solution for it.
I have a simple interface that returns a list of objects, based on a defined process.
public interface IDoStuff<out T>
{
IEnumerable<T> Do(string someParam);
}
i've created a couple of implementations for this interface. Then i have a view in wpf, which has a dropdown with hardcoded values, and depending on what you select, instatiates the implementation of the interface and populates some list
foreach (var item in new IDoSTuffImplementation1()<MyObj>.Do("imp 1"))
{
MyObjs.Add(item);
}
ater on MyObjs is the DataContext for a listview, and displays things and so on and so forth, but it's out of the main question.
this is all hardcoded and not very nice. If i was ever to implement a new interface, i'd need to add it to the dropdown, and create a new foreach for that specific implementation (more duplicated code)
Ok, here's my impression on making this better/refactoring for extensibility.
I was thinking a good approach would be to use some kind of MVVM pattern, making the wpf view into a view + viewmodel. the viewmodel would use some kind of IoC like spring, which would (by xml) instantiate one specific implementation of the interface, and inject it to the viewmodel, which would then call its "Do" method and everyone happy. So this way, the only thing that would be needed to do when we implement a new component, is to add it to the xml config file.
Suggestions, Comments? what's the best approach, if any?
thanks!!
Actually I don't see any architecture changes if you provide another implementation of the interface. You already have a good architecture when using MVVM, so the task you are trying to accomplish will not change the architecture, but will extend your application using the architecture.
I suggest you change you Method to a Property instead. And assign that property to ComboBox's ItemsSource property to ease up your coding using data binding.

Should a List<T> be private?

I need your opinion on this because I have read a lot of different things on the subject. If you have a List<T> or any kind of list within a class declaration do you make it private and then add or remove items using specific methods or do you make it public?
Your views would be much appreciated with any disadvantages/advantages of each option.
To give an example let's say we have a class Employer with private fields name and List<Employees>. My question is if we should make the employees list private or public and what the advantages/disadvantages be on either case.
for List explicitly yes it should be private depending on what the functionality you're exposing is supposed to do, interfaces such as IEnuemerable, ICollection or IList would be a better choice or if you're exposing a collection See SLaks reply.
Generally exposing internal structure and state is a bad idea and since your object of type List is both, you would want to keep it internal.
It might make sense to give the user the ability to iterate over it, to add or remove items to it but you should still keep the List internal and either expose Add/Remove methods or as a minimum expose an interface making it possible to change the type of the internal representation with out affecting the public interface.
Further more if you are exposing using an interface you should go for the narrowst possible interface.
So if the client code only needs to enumerate it. use IEnumerable if client code needs to index use ICollection and so forth.
further if you expose as an IEnumerable you should make sure that what ever you return is in fact read only by either using a read only collection class or by use of an iterator block
EDIT after update
In regards to your example. Ask yourself does it make sense that any one except the Employer can change who his employees are? to me that's in the words you've chosen already. The Employer employs the Employee and should have full control over who his/hers employees are. So in this particular case I'd keep it private and expose Hire(IEmployee employee) and Fire(IEmployee employee) that way the code plainly states the intent
If you need to expose a collection to your class' users, you should make a readonly property with a System.Collections.ObjectModel.Collection<T>.
You can then inherit this class and override InsertItem, RemoveItem, and SetItem to run custom logic when the user manipulates the collection.
If you don't want the user to be able to change the collection, you should expose a ReadOnlyCollection<T>.
In your specific example, you should probably expose a ReadOnlyCollection<Employee> with separate mutator methods in Employer.
And if all you want is for someone to be able to enumerate the list, you could expose an iEnumerable whose GetEnumerator function would simply call the list's GetEnumerator function.
As per the refactoring catalog its always better to encasulate the collections. This prevents some one from accidently currupting the data by adding or removing items from the list. If you don't need the functionality of protecting your data from accidental changes you can return a normal list.
By exposing the Add and Remove methods you get the advantage that any changes happens only through these methods.
Depends on the functionality you want. If you just want people to be able to manipulate the list, you could expose it through a read-only property (without the setter). If you want extra code to be executed when users manipulate the list, you should write your own methods, and not expose the list.

Categories

Resources