Best loose way to get objects with common base class - c#

I struggled to come up with a good title for this question, so suggestions are welcome.
Let's say we have an abstract base class ActionBase that looks something like this:
public abstract class ActionBase
{
public abstract string Name { get; }
public abstract string Description { get; }
// rest of declaration follows
}
And we have a bunch of different actions defined, like a MoveFileAction, WriteToRegistryAction, etc. These actions get attached to Worker objects:
public class Worker
{
private IList<ActionBase> _actions = new List<ActionBase>();
public IList<ActionBase> Actions { get { return _actions; } }
// worker stuff ...
}
So far, pretty straight-forward. Now, I'd like to have a UI for setting up Workers, assigning Actions, setting properties, and so on. In this UI, I want to present a list of all available actions, along with their properties, and for that I'd want to first gather up all the names and descriptions of available actions (plus the type) into a collection of the following type of item:
public class ActionDescriptor
{
public string Name { get; }
public string Description { get; }
poblic Type Type { get; }
}
Certainly, I can use reflection to do this, but is there a better way? Having Name and Description be instance properties of ActionBase (as opposed to statics on derived classes) smells a bit, but there isn't an abstract static in C#.
Thank you!

What you're talking about is creating Metadata for your concrete Action classes to describe them. For the simple case of Name and Description, I recommend the DisplayName and Description attributes like this:
[DisplayName("MyAction Name")]
[Description("My description goes here")]
public class MyAction : ActionBase
{
//Declaration goes here
}
These attributes are defined in System.ComponentModel.

You could add an abstract method to ActionBase which returns an ActionDescriptor, and then you could query each action for its descriptor.

Related

Implement IList<ISomeInterface> with List<SomeObjectThatImplementsISomeInterface>

I have a set of interfaces using each others like this:
public interface IModel
{
string Name { get; }
IModelParameters Parameters { get; }
}
public interface IModelParameter
{
int Value { get; }
}
public interface IModelParameters: IList<IModelParameter>
{
void DoSomething();
}
And to implement those interfaces, I have defined those classes:
public class Model: IModel
{
string Name { get; internal set; }
public ModelParameters Parameters { get; private set; }
IModelParameters IModel.Parameters { get { return Factors; } }
}
public class ModelParameter: IModelParameter
{
int Value { get; internal set; }
}
public class ModelParameters: List<ModelParameter>, IModelParameters
{
void DoSomething()
{
// actual code
}
}
This does not compile because List<ModelParameter> implements IList<ModelParameter> and not IList<IModelParameter> as required by IModelParameters
Changing ModelParameters to be List<IModelParameter> fixes the compilation but it breaks Entity Framework migration generation because it no longer recognizes the list as a navigation property because the type parameter is an interface, not a regular class.
I could also have ModelParameters not implement IModelParameters and declare a second class that gets instantiated and filled directly in the IModelParameters.Factors getter inside Model
But this feels inefficient as it effectively creates two instances of the same list, one for Entity framework and a temporary one for use by the rest of the application. And because this temporary is filled at runtime, it introduces another potential point of failure.
This is why I'm trying to find a way to express the fact List<ModelParameter> implements IList<IModelParameter> just fine because ModelParameter implements IModelParameter itself.
I have a feeling that covariance/contravariance might be of help here, but I'm not sure how to use that.
You cannot do this. It it was possible to cast a List<ModelParameter> to IList<IModelParameter> you could try adding a object of another type to the list, i.e. class MyOtherModelParam : IModelParameter. And that is a contradiction since the type system guarantees that the list only contains ModelParameter objects.
You could replace it with IReadOnlyList<T>, since this interface do not expose any add or set methods it is safe to cast a List<ModelParameter> to IReadOnlyList<IModelParameter>.
Another possible solution would be to just remove the interface. If you intend to have only one implementation of IModelParameter, the interface serves little purpose, and you might as well just remove it.

How to abstract Entity Framework model properties

I have a model that looks like this :
public class Task : ITask
{
public int DocumentId { get; set; }
public virtual Document Document { get; set; }
public TaskType TaskType { get; }
public string Value { get; }
}
Now, this class is directly registered as a DbSet in the DbContext.
This means that the Document property must be of concrete type. I want to make this code easily testable, so I want to have the property as an interface which is required by the ITask interface. What is the general way to approach this problem?
One way that comes to my mind is to put all such classes in a separate assembly but that seems a bit off.
Edit: The ITask interface is defined in a different assembly so it should not know about the Document type.
I would use EF models only for the data access layer and create a separate model for the business layer. The data access layer would be responsible for mapping the EF model to the business layer model and hand it to the business layer.
The business layer model can then also be immutable, which can have advantages. Also you can require all the properties to be e.g. not-null in you constructor and you can then rely on this throughout the whole business layer.
Of course you could argue that it's almost twice as much code to write. That's true, but IMO it results in cleaner code and therefore this is my preferred approach.
Interfaces can have properties defined in them, So your ITask can specify the document, like this:
public interface ITask {
Document Document { get; set; }
}
But you also say that you want the Document property as an interface and this becomes tricky as you need a concrete type in the Task class. Generic interfaces will help here.
// The interfaces
public interface ITask<TDocument> where TDocument : IDocument, new() {
TDocument Document { get; set; }
}
public interface IDocument {
int Number { get; set; } // Example property
}
//The classes
public class Document : IDocument{
public int Number { get; set; } // Example property
}
public class Task : ITask<Document> {
public Document Document { get; set; }
}
// See if it works
public class Test {
private Task myTask = new Task();
public void TestMethod() {
myTask.Document.Number = 1;
}
}
Remember, use the concrete types in DBContext.
As to where the interfaces should be located, same assembly or their own, there's quite a few viewpoints on that. Personally, I put them in their own assembly away from the implementing classes. This question is worth a read:
Should I have a separate assembly for interfaces?
One more comment, the class name Task is used in the .Net threading library, so maybe worth thinking about changing it to avoid potential confusion.

Why use extension methods, if you could do a normal method?

Could someone, please, explain why an answer in this question advocates usage of extension methods while defining base interfaces.
- Why not including the the SteerLeft() and Stop() methods in their respective interfaces? - Is it to illustrate adding behaviors that should not/could not be anticipated/forced by the "base"?
- Isn't it better to "force" something as basic as "steering" behavior when you're requiring a steering wheel?
Below, I've extracted relevant code. The answering person states:
you could use the Extension Methods feature added to C# 3.0 to
further simplify calling methods on those implied properties
public interface ISteerable { SteeringWheel wheel { get; set; } }
public interface IBrakable { BrakePedal brake { get; set; } }
public class Vehicle : ISteerable, IBrakable
{
public SteeringWheel wheel { get; set; }
public BrakePedal brake { get; set; }
public Vehicle() { wheel = new SteeringWheel(); brake = new BrakePedal(); }
}
public static class SteeringExtensions
{
public static void SteerLeft(this ISteerable vehicle)
{
vehicle.wheel.SteerLeft();
}
}
public static class BrakeExtensions
{
public static void Stop(this IBrakable vehicle)
{
vehicle.brake.ApplyUntilStop();
}
}
public class Main
{
Vehicle myCar = new Vehicle();
public void main()
{
myCar.SteerLeft();
myCar.Stop();
}
}
The point of using extension method is that you can add method to an existing .Net class even if you do not have the Source code or it reside within different assembly.
And extension method helps to
These methods can be added later (than type authoring time) after type has already been published.
Extension methods can target interfaces.
Different people can extend the same type differently as per their needs.
Take LINQ for example it provides Methods that work on any IEnumerable type!
EM are not some substitute of multiple inheritance and is not an inheritance mechanism. It's just a tool, like name suggests, to extend functionality of some type by your means.
In this concrete code there is no much sense of using EM. As you noted, you can easily extend functionality of the class, just by adding a new method inside its body.
EM are extremely useful in cases when you can not change original source of a class or not allowed to do so.

Is this class structure method correct/desireblable? (MVC/C#)

I'm building a MVC application which is a bit more complex than what I usually do and I want to try a new class structure. Basically theres a lot of reading going on. Just 5-10% of operations will be insert/update against the database.
Because of this, I'm thinking of creating base DTO classes which would be returned from a database layer. Then, business objects would inherit from the DTO class in order to extend the basic structure with all the validation and business rules.
Example:
namespace Project.DTO
{
public class Employee
{
public string Name;
public string Surname;
...
}
}
namespace Project
{
public class Employee : Project.DTO.Employee
{
public bool IsValid()
{
...
}
}
}
Is this a good approach? What I haven't thought off yet is how to use them inside the MVC, as the "correct" way would be to implement model classes. I believe I could create model classes that inherited from the DTO objects as well... but I'm unsure.
I would also need a way to handle all validation functions with some kind of Interface, as to avoid repeating to much generic code on the GUI.
Thanks in advance!
I would probably use a completely different approach. My primary thoughts are these:
I would like looser coupling between the classes, so I would not have my model classes inherit from my DTO objects
I would probably not include validation logic in my model classes
This would lead to the following structure to start with:
namespace Project.DTO
{
public class Employee
{
public string Name;
public string Surname;
...
}
}
namespace Project
{
public class Employee
{
public string Name { get; set; }
public string Surname { get; set; }
}
}
When it comes to the validation logic, I would make an interface for the validation logic, that is injected into the Emplyee class:
public interface IValidator<T>
{
bool IsValid(T objectToInspect);
}
public class Employee
{
private readonly IValidator<Employee> validator;
public Employee(IValidator<Employee> validator)
{
this.validator = validator;
}
public string Name { get; set; }
public string Surname { get; set; }
public bool IsValid()
{
return validator.IsValid(this);
}
}
This opens up your design for a whole range of features, including using IoC containers and better support for testing.
What if validation has to check with a rule whose parameters must come from database? Your entity would not have a knowledge and the way to access that parameter.
Creating Model/ViewModel is good but validation usually require more complex logic which would warrant dedicated classes - so I would not normally implement IsValid on my entity.
However, you can use System.Component.DataAnnotation validation attributes against simple properties of your entities.

Anybody have a clever way to treat a DTO as more of an OO class?

I have a set of DataContracts that are serialzed through WCF.
Please note this is a very simplified example.
[DataContract]
public class MyData
{
[DataMember]
public List<int> MyList
{
get;
set;
}
}
I would like to use object oriented design so that the server and client aren't creating any unnecessary dependencies. For example, I would like to encapsulate a list so that the user can't directly modify it.
Ideally, I would like the class to look like this if it wasn't a DTO.
public class MyData
{
private List<int> _list = new List<int>();
public IEnumerable<int> MyList
{
get
{
return _list;
}
}
public void AddItem( int value )
{
_list.Add( value );
}
}
I am using the same C# assembly from both the service and the client. So I can add non-DataMember methods, but I'm not sure if that is a good approach. It doesn't smell quite right to me.
Does anybody have a clever way of treating DTO classes more like objects instead of simple serializable structures?
How about having DTO versions of your logic class which are used solely for the purpose of message passing?
That way, you can put all the methods and properties on your logic class as necessary without having to worry about what the user has access to when it's passed over the wire. There are many ways you can go about this, for instance:
you can implement some method on your logic class to return the DTO
public class Player
{
// methods that do interesting things here
...
public string Name { get; set; }
public PlayerDTO ToTransport()
{
return new PlayerDTO { Name = Name, ... };
}
}
[DataContract]
public class PlayerDTO
{
[DataMember]
public string Name { get; set; }
...
}
Or you can implement an explicit/implicit conversion
public class Player
{
// methods that do interesting things here
...
public string Name { get; set; }
}
[DataContract]
public class PlayerDTO
{
[DataMember]
public string Name { get; set; }
...
public static explicit operator PlayerDTO(Player player)
{
return new PlayerDTO { Name = player.Name, ... };
}
}
this lets you cast a Player object to PlayerDTO:
var player = new Player { Name = .... };
var dto = (PlayerDTO) player;
Personally, I do think having DataContract on objects which are for more than service operations is a bit of a smell, just as it would be for ORM column mappings. One somewhat limited way to make these DTOs more like true OO is to have your methods be extension methods of the DTO. You might need to do something creative if the OO version has state that needs to be captured between calls that is not inherent in the DTO object itself, though.
I do not think having methods unadorned by attributes in your DataContract's class necessarily smells. You have your service-oriented concerns on one hand (the operation and data contracts) and your object-oriented concerns on the other. What the client does with the provided data is of no concern to the service. The object-oriented issue you describe really only exists for the client.
If a client obtained Ball data from your service and it wants to Draw() it to the screen, whether or not the Ball class has a Draw() method has nothing to do with the contract between service and client. It is a contract between the api your assembly provides and those that use it. So I say, why not have a method in the assembly that is not an operation/data contract?

Categories

Resources