How to handle compiled classes in C #

What I ask is partly related to the design pattern.

Suppose I have an IDrawing interface. Two other base classes called TextDrawing and ShapeDrawing implement this, and I have a View class that knows how to draw them!

But I have more complex drawing classes that also implement the IDrawing interface, but consist of several IDrawing classes!

How to do it in the View class? Obviously, teaching the View class to draw each new IDrawing is not a good idea! But what other options do I have? Maybe the design is wrong? How can I learn the View Draw method to find out the primitive parts of complex classes and draw them?

public interface IDrawing { } public class TextDrawing : IDrawing { } public class ShapeDrawing : IDrawing { } public class SignDrawing : IDrawing { public TextDrawing Text { get; set; } public ShapeDrawing Border { get; set; } } public class MoreComplexDrawing : IDrawing { public TextDrawing Text { get; set; } public ShapeDrawing Border1 { get; set; } public ShapeDrawing Border2 { get; set; } } public class View { public void Draw(IDrawing drawing) { // The View only knows how to draw TextDrawing and ShapeDrawing. // These as the primitive building blocks of all drawings. // How can it draw the more complex ones! if (drawing is TextDrawing) { // draw it } else if (drawing is ShapeDrawing) { // draw it } else { // extract the drawings primitive parts (TextDrawing and ShapeDrawing) and draw them! } } } 

Update:

I received suggestions for implementing the Draw () method in my drawing classes. The Draw method in the view relies on an external drawing library (in my case, it is the SkiaSharp library). If I implement Draw in these classes, they won’t be at all anymore! For example, I will not be able to use them in other projects where I have a different strategy for drawing.

+5
source share
3 answers

I would add the Draw() method to the interface and implement it in each of your classes.

The advantage of this is that your View doesn't care what the actual type is.

 public interface IDrawing { void Draw(); } public class TextDrawing : IDrawing { public void Draw() { // Draw a TextDrawing } } public class ShapeDrawing : IDrawing { public void Draw() { // Draw a ShapeDrawing } } public class SignDrawing : IDrawing { public TextDrawing Text { get; set; } public ShapeDrawing Border { get; set; } public void Draw() { // Draw a SignDrawing } } public class MoreComplexDrawing : IDrawing { public TextDrawing Text { get; set; } public ShapeDrawing Border1 { get; set; } public ShapeDrawing Border2 { get; set; } public void Draw() { // Draw a MoreComplexDrawing } } public class View { public void Draw(IDrawing drawing) { //Draw the drawing drawing.Draw(); } } 

UPDATE - drop SkiaSharp addiction

You will need to create a wrapper for SkiaSharp or any external dependency that actually does the drawing. This should exist in the same assembly as your IDrawing interface and derived classes.

 public interface IDrawingContext { // Lots of drawing methods that will facilitate the drawing of your `IDrawing`s void DrawText(...); void DrawShape(...); void DrawBorder(...); } 

In addition to the specific implementation of SkiaSharp

 public class SkiaSharpDrawingContext IDrawingContext { // Lots of drawing methods that will facilitate the drawing of your IDrawings public void DrawText(...) { /* Drawing code here */ } public void DrawShape(...) { /* Drawing code here */ } public void DrawBorder(...) { /* Drawing code here */ } } 

Update the IDrawing interface to

 public interface IDrawing { void Draw(IDrawingContext drawingContext); } 

Updating your classes to reflect this change. Your classes will call IDrawingContext implementation methods to draw the drawing.

Create a specific dependency implementation in your applications and update your View class to use the new SkiaSharpDrawingContext

 public class View { public void Draw(IDrawing drawing) { // This should ideally be injected using an IOC framework var drawingContext = new SkiaSharpDrawingContext(...); //Draw the drawing drawing.Draw(drawingContext); } } 
+5
source

You have a choice to force classes to implement a method called Draw() .

 public interface IDrawing { void Draw(); } 

Now you can simply call this method and take responsibility for the internal implementation of the classes yourself.

 public void Draw(IDrawing drawing) { drawing.Draw(); 

For example, TextDrawing will be forced to implement this method.

 public class TextDrawing : IDrawing { public void Draw() { // draw Text-like } } 

In your View class, the call to drawing.Draw(); will lead to proper implementation.

How can I learn the View Draw method to find out the primitive parts of complex classes and draw them?

Now in complex classes, you simply use methods that are already implemented in simple drawing classes.

 public class SignDrawing : IDrawing { public TextDrawing Text { get; set; } public ShapeDrawing Border { get; set; } public void Draw() { Text.Draw(); Border.Draw(); Text.Draw(); } } 
+4
source
 you can polymorphically draw without checking the type. public class View { public void Draw(IDrawing drawing) { drawing.Draw(); } } Encapsulate each drawing strategy (Strategy Pattern) in different class and you could inject each strategy via DI. 
+2
source

Source: https://habr.com/ru/post/1271161/


All Articles