.NET class design question - c#

I have a class called Question that has a property called Type. Based on this type, I want to render the question to html in a specific way (multiple choice = radio buttons, multiple answer = checkboxes, etc...). I started out with a single RenderHtml method that called sub-methods depending on the question type, but I'm thinking separating out the rendering logic into individual classes that implement an interface might be better. However, as this class is persisted to the database using NHibernate and the interface implementation is dependent on a property, I'm not sure how best to layout the class.
The class in question:
public class Question
{
public Guid ID { get; set; }
public int Number { get; set; }
public QuestionType Type { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
}
Based on the QuestionType enum property, I'd like to render the following (just an example):
<div>[Content]</div>
<div>
<input type="[Depends on QuestionType property]" /> [Answer Value]
<input type="[Depends on QuestionType property]" /> [Answer Value]
<input type="[Depends on QuestionType property]" /> [Answer Value]
...
</div>
Currently, I have one big switch statement in a function called RenderHtml() that does the dirty work, but I'd like to move it to something cleaner. I'm just not sure how.
Any thoughts?
EDIT: Thanks to everyone for the answers!
I ended up going with the strategy pattern using the following interface:
public interface IQuestionRenderer
{
string RenderHtml(Question question);
}
And the following implementation:
public class MultipleChoiceQuestionRenderer : IQuestionRenderer
{
#region IQuestionRenderer Members
public string RenderHtml(Question question)
{
var wrapper = new HtmlGenericControl("div");
wrapper.ID = question.ID.ToString();
wrapper.Attributes.Add("class", "question-wrapper");
var content = new HtmlGenericControl("div");
content.Attributes.Add("class", "question-content");
content.InnerHtml = question.Content;
wrapper.Controls.Add(content);
var answers = new HtmlGenericControl("div");
answers.Attributes.Add("class", "question-answers");
wrapper.Controls.Add(answers);
foreach (var answer in question.Answers)
{
var answerLabel = new HtmlGenericControl("label");
answerLabel.Attributes.Add("for", answer.ID.ToString());
answers.Controls.Add(answerLabel);
var answerTag = new HtmlInputRadioButton();
answerTag.ID = answer.ID.ToString();
answerTag.Name = question.ID.ToString();
answer.Value = answer.ID.ToString();
answerLabel.Controls.Add(answerTag);
var answerValue = new HtmlGenericControl();
answerValue.InnerHtml = answer.Value + "<br/>";
answerLabel.Controls.Add(answerValue);
}
var stringWriter = new StringWriter();
var htmlWriter = new HtmlTextWriter(stringWriter);
wrapper.RenderControl(htmlWriter);
return stringWriter.ToString();
}
#endregion
}
The modified Question class uses an internal dictionary like so:
public class Question
{
private Dictionary<QuestionType, IQuestionRenderer> _renderers = new Dictionary<QuestionType, IQuestionRenderer>
{
{ QuestionType.MultipleChoice, new MultipleChoiceQuestionRenderer() }
};
public Guid ID { get; set; }
public int Number { get; set; }
public QuestionType Type { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
public string RenderHtml()
{
var renderer = _renderers[Type];
return renderer.RenderHtml(this);
}
}
Looks pretty clean to me. :)

Generally speaking, whenever you see switches on a Type or Enum, it means you can substitute in objects as the "Type" - said differently, a case for polymorphism.
What this means practically is that you'll create a different class for each Question type and override the RenderHTML() function. Each Question object will be responsible for knowing what input type it ought to output.
The benefits are that you remove the switch statement as well as produce good OO based code. The draw backs are that you add a class for every Question type (in this case minimal impact.)

You can for example use the strategy pattern:
Have all your HTML renderers implement a common interface, for example IQuestionRenderer, with a method name Render(Question).
Have an instance of Dictionary<QuestionType, IQuestionRenderer> in your application. Populate it at initialization time, perhaps based on a configuration file.
For a given instance of a question, do: renderers[question.Type].Render(question)
Or, you could have methods named RenderXXX where XXX is the question type, and invoke them by using reflection.

This is a classic case for using object inheritance to achieve what you want. Anytime you see a big switch statement switching on the type of an object, you should consider some form of subclassing.
I see two approaches, depending on how "common" these question types really are and whether rendering is the only difference between them:
Option 1 - Subclass the Question class
public class Question
{
public Guid ID { get; set; }
public int Number { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
public virtual string RenderHtml();
}
public class MultipleChoiceQuestion
{
public string RenderHtml() {
// render a radio button
}
}
public class MultipleAnswerQuestion
{
public string RenderHtml() {
// render a radio button
}
}
Option 2 - Create a render interface, and make that a property on your question class
public class Question
{
public Guid ID { get; set; }
public int Number { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
public IRenderer Renderer { get; private set; }
}
public interface IRenderer {
void RenderHtml(Question q);
}
public class MultipleChoiceRenderer : IRenderer
{
public string RenderHtml(Question q) {
// render a radio button
}
}
public class MultipleAnswerRenderer: IRenderer
{
public string RenderHtml(Question q) {
// render checkboxes
}
}
In this case, you would instantiate the renderer in your constructor based on the question type.
Option 1 is probably preferable if question types differ in more ways than rendering. If rendering is the only difference, consider Option 2.

It's a good idea to separate the rendering logic into its own class. You don't want rendering logic embedded into the business logic of your application.
I would create a class called QuestionRenderer that takes in a Question, reads its type, and outputs rendering accordingly. If you're using ASP.NET it could output webcontrols, or you could do a server control that outputs HTML.

Why not have a QuestionRenderer class (actually, it will be a control) which exposes a Question as a property which you can set.
In the render method, you can decide what to render based on the question type.

I don't like the idea of rendering details being in the same class as the data.
So, one option would be to have your rendering method simply generate one of a set of user controls that handled the actual HTML rendering.
Another would be to have a separate class QuestionRenderer which would have the various subclasses for question types (each of which would render the correct HTML).

I think what you want is an IUserType that convert the property from the hibernate mapping to the correct control type via some Question factory.
An example of the use of an IuserType can be found here:
NHibernate IUserType
in the example it converts a blob to an image for use on the client side but with the same idea you can make your page created with the QuestionType.

You could use the strategy pattern (Wikipedia) and a factory in combination.
public class Question
{
public Guid ID { get; set; }
public int Number { get; set; }
public QuestionType Type { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
private IQuestionRenderer renderer;
public RenderHtml()
{
if (renderer == null)
{
QuestionRendererFactory.GetRenderer(Type);
}
renderer.Render(this);
}
}
interface IQuestionRenderer
{
public Render(Question question);
}
public QuestionRendererA : IQuestionRenderer
{
public Render(Question question)
{
// Render code for question type A
}
}
public QuestionRendererB : IQuestionRenderer
{
public Render(Question question)
{
// Render code for question type B
}
}
public QuestionRendererFactory
{
public static IQuestionRenderer GetRenderer(QuestionType type)
{
// Create right renderer for question type
}
}
Only the public properties need to be included in NHibernate.

The rendering is definitely a UI concern, so I'd separate that from the Question class and add a factory to isolate the switching logic (the QuestionControl base class inherits from WebControl and would contain the majority of the rendering logic):
RadioButtonQuestionControl: QuestionControl {
// Contains radio-button rendering logic
}
CheckboxListQuestionControl: QuestionControl {
// Contains checkbox list rendering logic
}
QuestionControlFactory {
public QuestionControl CreateQuestionControl(Question question) {
// Switches on Question.Type to produce the correct control
}
}
Usage:
public void Page_Load(object sender, EventArgs args) {
List<Question> questions = this.repository.GetQuestions();
foreach(Question question in Questions) {
this.Controls.Add(QuestionControlFactory.CreateQuestionControl(question));
// ... Additional wiring etc.
}
}

Stating the obvious: You could probably use a factory method to get the instance of the required rendered class and call render on that to get the required output.

The approach I would take is to create a separate Control (or a HtmlHelper method if you're in MVC) for each visual style you would like your questions to be rendered using. This separates the concerns of representing the question as an object and representing it visually neatly.
Then you can use a master Control (or method) to choose the correct rendering method based on the type of the Question instance presented to it.

Related

Is this a valid use of the new keyword in my interface? [duplicate]

Is it advisable to use the "new" keyword in a derived interface to provide a more-derived return value for a property or method having the same name?
Say I have an interface IDocument:
public interface IDocument
{
IParagraphs Paragraphs { get; }
IRevisions Revisions { get; }
IStyles Styles { get; }
}
And a derived one IRtfDocument.
public interface IRtfDocument: IDocument
{
string Rtf { get; }
...
}
I also have more-derived interfaces for IParagraphs, IRevisions and IStyles: IRtfParagraphs, IRtfRevisions, IRtfStyles. A number of RTF-specific needs drove their creation.
When I access the paragraphs of an RTF document, I'd like to avoid casting them to IRtfParagraphs. Same for revisions and styles. It would also be nice to avoid having both "IRtfParagraphs" and "IParagraphs". So what I'd like to do is this:
public interface IRtfDocument : IDocument
{
new IRtfParagraphs Paragraphs { get; }
new IRtfRevisions Revisions { get; }
new IRtfStyles Styles { get; }
string Rtf { get; }
}
Is this considered good practice? It seems to fit in this situation, but I wanted to run it by you C# veterans.
Update: So I actually went ahead and tried using "new" as described in my interfaces. My RtfDocument class ended up needing both an IDocument.Styles property and an IRtfDocument.Styles property. While I could just have the IDocument.Styles property return the value of IRtfDocument.Styles, that doesn't feel quite right as I'm implementing two properties.
It seems the compiler doesn't account for the fact that IRtfStyles derives from IStyles, so it insists I have both. It would be nice if the Liskov Substitution Principle let me just implement IRtfDocument.Styles in the RtfDocument class.
The easier solution would probably just be to have a generic interface:
public interface IFooBox<T>
where T : IFoo
{
T Foo { get; }
}
You can then have an IFooBox<IFoo> for your basic objects, or an IFooBox<IEnhancedFoo> for the enhanced version.
This type of definition will force implementers of IEnhancedFooBox to explicitly implement IFoo.Foo separately from the implementation of IEnhancedFooBox.Foo. Since this work gets tedious, I tend to reserve this for cases where a generic interface extends a non-generic interface.
For example, consider the following interfaces.
interface IFutureValue {
object Result { get; }
}
interface IFutureValue<T> : IFutureValue {
new T Result { get; }
}
It is possible to implement a general handler for all "future values" by working with IFutureValue, where code working with future values of a specific type can work with IFutureValue<T>.
To answer the question,
Is this considered good practice?
The use of new is frowned upon, in general. However, as with all frowning in programming, it is a matter of judgement. If you have found a use for new that makes sense in your context, and you've ruled out other avenues like #Servy's example, then rock the new. Be prepared to defend your decision though.
There is big potential problem with your use of the new modifier. Suppose we use your interfaces:
public interface IFoo
{
string Name { get; set; }
}
public interface IEnhancedFoo : IFoo
{
int BarCount { get; set; }
}
public interface IFooBox
{
IFoo Foo { get; set; }
}
public interface IEnhancedFooBox : IFooBox
{
new IEnhancedFoo Foo { get; set; }
}
Build out our classes:
public class EnhancedFooBox : IEnhancedFooBox
{
public IEnhancedFoo Foo { get; set; }
IFoo IFooBox.Foo { get; set; }
}
public class FooBase : IFoo
{
public string Name { get; set; }
}
public class EnhancedFoo : IEnhancedFoo
{
public int BarCount { get; set; }
public string Name { get; set; }
}
Build some methods that take interfaces...
static void Test1(IFooBox myBlah)
{
myBlah.Foo = new FooBase();
myBlah.Foo.Name = "FooBase";
}
static void Test2(IEnhancedFooBox myBlah)
{
myBlah.Foo = new EnhancedFoo();
myBlah.Foo.Name = "EnhancedFoo";
}
And then use this logic:
static void Main(string[] args)
{
var myBlah = new EnhancedFooBox();
Test2(myBlah); //first assign name to EnhancedFoo
Test1(myBlah); //second assign name to FooBase
Console.Write(myBlah.Foo.Name);
Console.ReadKey();
}
What is the expected output? Should it be FooBase or EnhancedFoo?
EnhancedFoo
Programmers unaware the property has been modified to new, will not get the expected output. This is solved using generics.

c# what kind of design pattern should i use when a class has image and color property

Actually,I work an application about map simulation,Element represent something with id and name:
public abstract class Element
{
public string Id { get; set; }
public string Name { get; set; }
public abstract void Display();
public abstract void Stop();
public abstract void Refresh();
}
And Device is something like radar or radio device,they all have id and class,so Device inherit Element:
public abstract class Device:Element
{
}
and Target calss is something like radar station,radio station with a position property,
public class Target : Element
{
public Position Position { get; set; }
public List<Device> Devices { get; private set; }
public List<Target> Targets { get; private set; }
public override void Display()
{
//throw new NotImplementedException();
}
public override void Refresh()
{
//throw new NotImplementedException();
}
public override void Stop()
{
//throw new NotImplementedException();
}
}
Position is a struct :
public struct Position
{
public double Lat { get; set; }
public double Lng { get; set; }
public Position(double lat, double lng)
{
Lat = lat;
Lng = lng;
}
}
There is also a class named Platform inherit Target,which means a ship or a plane,they can move from one position to another.
public class Platform : Target
{
public double Speed { get; set; }
public void Move()
{
}
}
All these classes should be in BL,that's no problem.But in UI, Device or Target should have Color and image proerty to show in map control(GMap.net,use image to GMapMarker).For the reason of split ui from bl,image or color will not allowed in BL.The question is:
Is there some design patterns or elegant way to handle this situation?
Thanks!
Design patterns provide general solution to commonly occurring design problem.
I would like you to follow below approach.
Understand intent of each pattern
Understand checklist or use case of each pattern
Think of solution to your problem and check if your solution falls
into checklist of particular pattern
If not, simply ignore the design-patterns and write your own solution.
Useful links:
https://sourcemaking.com/design_patterns: Explains intent, structure and checklist beautifully in multiple languages including C++ and Java
wikipedia : Explains structure, UML diagram and working examples in multiple languages including C# and Java .
Check list and Rules of thumb in each sourcemakding design-pattern provides alram bell you are looking for.
As per your requirement I think Repository Design pattern is best for you.
If you want to assign image and color to an element then you may have them in model(in your Element class). Initially they would be null but later you may assign them values. I suppose your models are shared between BL and UI.

Have a wrapper object expose its wrapee's properties

I'm currently trying to figure out how to have a wrapper class expose the properties of whatever it is wrapping without having to manually set them one by one in the wrapper class. I've been trying to figure out if this is even a good design choice or if I'm totally misguided and going off into a very bad placeā„¢ by doing this.
I also already have my wrapper class inheriting something...
Example code below (fake objects so don't read into them please):
public class Car {
public String Name { get; set; }
public String Status { get; set; }
public String Type { get; set; }
public Car(takes params) {
// makes car!
}
}
public class CarWrapper : OtherAutomotiveRelatedThing {
public Car car;
public CarWrapper(Car c) {
car = c;
}
}
public class OtherAutomotiveRelatedThing {
public String Property1 { get; protected set; }
public String Property2 { get; protected set; }
}
I'm using inheritance on the wrapper object because I can not modify the base Car class and it needs the properties of other automotive thing. Multiple other classes inherit from OtherAutomotiveRelatedThing as well.
I return a list of the CarWrapper objects as Json (because I'm building a web app) and the wrapper object is causing problems for me. When cast/converted to Json the CarWrapper objects in the list all contain another nested object - the Car object and the framework I'm using can't get at its properties to do what it needs.
Is there a way to expose the wrapped Car object's properties at the "top level" of the CarWrapper without doing the following:
public class CarWrapper : OtherAutomotiveRelatedThing {
public Car car;
public String Name { get; private set; }
public String Status { get; private set; }
public String Type { get; private set; }
public CarWrapper(Car c) {
car = c;
this.Name = c.Name;
this.Status = c.Status;
this.Type = c.Type;
}
}
Please let me know if I'm not being clear, if you have any questions, or need/want more info.
Thanks!
For me it looks like you want prototype-style programming like in JavaScript, which is not they use in OOP.
Maybe it's good start to think of it as "If I have two different car wrappers (with differnt properties set), how should I pass any of them a method?" or "Can I have a single wrapper which wraps Car and Animal", and "How to expose public property which has the same name but different meaning for Car and Animal, like skin color?" etc
Answers may help you identify if you need say interfaces, or wrappers which expose public objects, or pure encapsulation, or changing language to say JavaScript.

Classes in razor engine template

Is it possible to create classes within a template? Something like...
#{
public class MyClass {
public MyClass() {
Three = new List<string>();
}
public string One { get; set; }
public int Two { get; set; }
public List<string> Three { get; set; }
}
}
Currently I get "Unable to compile template. Check the Errors list for details." when I try to do this. I would like to take XML content and use XmlSerializer to create an instance of MyClass within the template. I can't do the deserialization before hand and shove it into the model because the classes could vary depending on the template.
Yes, this is completely possible. Use the #functions keyword:
#functions {
public class MyClass {
public MyClass() {
Three = new List<string>();
}
public string One { get; set; }
public int Two { get; set; }
public List<string> Three { get; set; }
}
}
I'll post my response from the CodePlex Discussion here:
I'm not sure that is currently possible. When you use codeblocks (#{ }), you're actually writing code within a method, e.g. your above code would do something like:
public void Execute()
{
this.Clear();
public class MyClass {
public MyClass() {
Three = new List<string>();
}
public string One { get; set; }
public int Two { get; set; }
public List<string> Three { get; set;}
}
}
...which of course, is not valid C#. The other problem you will face, is that to use xml serialisation/deserialisation, the type must be known, but if you are defining your type within the template itself, how could you deserialise it in the first place?
What you could do, is use a custom base template:
public class CustomTemplateBase<T> : TemplateBase<T>
{
public dynamic Instance { get; set; }
public dynamic CreateInstance(string typeName)
{
Type type = Type.GetType(typeName);
// You'd to your deserialisation here, I'm going to
// just cheat and return a new instance.
return Activator.CreateInstance(type);
}
}
Using a dynamic property and dynamic return type, we've defined a method that will let us create an instance (through activation or deserialisation, etc.) and call member access on it. To use that in a template, you could then do:
#{
Instance = CreateInstance("ConsoleApplication1.MyClass, ConsoleApplication1");
Instance.One = "Hello World";
}
<h1>#Instance.One</h1>
Where "MyClass" is a defined somewhere in my application. The important thing is, I'm creating an instance per template.
I would suggest using a specific ViewModel class, which could have a dynamic property (ExpandoObject) allowing you to populate it with any custom data structure as needed while still communicating strongly typed for whatever else your view might need.
This also keeps your view models separate from the views themselves, which is good practice (html and code don't mix too well where readability is a concern).

design pattern to remove multiple if/else clauses with related objects

I have inherited the following (terrible) code and am wondering how best to refactor it.
There are large if/else clauses all over the codebase, one of which is similar to below :
public class BaseResultItem
{
public int Property1 { get; set; }
}
public class ResultItem1 : BaseResultItem
{
public int Property2 { get; set; }
}
public class ResultItem2 : BaseResultItem
{
public int Property3 { get; set; }
}
public class BaseHistoryItem
{
public int Property1 { get; set; }
}
public class HistoryItem1 : BaseHistoryItem
{
public int Property2 { get; set; }
}
public class HistoryItem2 : BaseHistoryItem
{
public int Property3 { get; set; }
}
public class HistoryBuilder
{
public BaseHistoryItem BuildHistory(BaseResultItem result)
{
BaseHistoryItem history = new BaseHistoryItem
{
Property1 = result.Property1
};
if (result is ResultItem1)
{
((HistoryItem1)history).Property2 = ((ResultItem1)result).Property2;
}
else if (result is ResultItem2)
{
((HistoryItem2)history).Property3 = ((ResultItem2)result).Property3;
}
return history;
}
}
Note that this is a simplified example and there are many more classes involved in the actual code. There are similar if/else clauses all over the place.
I have been looking at the abstract factory pattern but I am having some problems.
Basically I am assuming that to avoid the if/else problems I need to pass the actual dervied types around. So BuildHistory should not use base types and maybe there should be multiple methods, one per derived type?
If you can't change the DTO classes perhaps you can try to subclass HistoryBuilder to deal with the different subclasses. Then you use the appropriate HistoryBuilderX to create a HistoryItem from a ResultItem. Then the question is how to get the appropriate HistoryBuilderX for the ResultItem supplied.
Still, if you can't change the BaseResultItem class to include a GetBuilder function you need to use some if..else if.. construct that inspects the classtypes of your ResultItems.
Or you create a Registry where every ResultItem class is registered with its corresponding HistoryBuilderX class. But that might be overkill.
The general 'design pattern' is simply to use object orientation with polymorphism instead of type checks. Thus: a BuildHistory method inside BaseResultItem, overridden by descendants.
Any code which checks the concrete type of an object smells (in a refactoring sense). Supporting different behaviours for different types is what OO is about.
Use polymorphism to remove the type checks.
if (result is ResultItem1)
{
((HistoryItem1)history).Property2 = ((ResultItem1)result).Property2;
}
Becomes then something like
result.addToHistory( history );
If for some reason, you don't want to scatter the logic in the item classes, have a look at the visitor pattern. In this case, you have something like:
public class Visitor {
History history;
public visit ( ResultItem1 item ) { ... }
public visit ( ResultItem2 item ) { ... }
...
}
public class ResultItem1 {
public accept( Visitor v ) { v.visit( this ); }
}
The typecheck is removed by the double-dispatch in the visitor, which is slightly more elegant.
I didn't understood exactly how the various kind of history relates to the various kind of items. So this is just a sketch of possibles direction to follow.

Categories