How to abstract Entity Framework model properties - c#

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.

Related

Design Pattern to use for customizable/extendable classes with constructors

Starting with the use case.
Let's consider the base for this questions is a big framework and implementations of business objects of some software.
This software hast to be customized quite regularly, so it would be preferred that most of the C# objects are extendable and logic can be overriden. Even "model data".
The goal would be to be able to write code, create objects with input parameters - that may create more objects etc - and you don't have to think about whether those objects have derived implementations in any way. The derived classes will be used automatically.
For ease of uses a typesafe way to create the objects would be preferred as well.
A quick example:
public class OrderModel
{
public int Id { get; set; }
public string Status { get; set; }
}
public class CustomOrderModel : OrderModel
{
public string AdditionalData { get; set; }
}
public class StockFinder
{
public Article Article { get; }
public StockFinder(Article article)
{
Article = article;
}
public virtual double GetInternalStock() { /*...*/ }
public virtual double GetFreeStock() { /*...*/ }
}
public class CustomStockFinder : StockFinder
{
public bool UsePremiumAvailability { get; }
public CustomStockFinder(Article article, bool usePremiumAvailability)
: base(article)
{
UsePremiumAvailability = usePremiumAvailability;
}
protected CustomStockFinder(Article article) : this(article, false) { } // For compatibility (?)
public override double GetFreeStock() { /*...*/ }
}
In both cases I wanna do stuff like this
var resp = Factory.Create<OrderModel>(); // Creates a CustomOrderModel internally
// Generic
var finderGeneric = Factory.Create<StockFinder>(someArticle);
// Typesafe?
var finderTypesafe1 = Factory.StockFinder.Create(someArticle); // GetFreeStock() uses the new implementation
var finderTypesafe2 = Factory.StockFinder.Create(someArticle, true); // Returns the custom class already
Automatically generating and compiling C# code on build is not a big issue and could be done.
Usage of Reflection to call constructors is okay, if need be.
It's less about how complicating some code generation logic, written code analyzers, internal factories, builders etc are, and more about how "easy" and understandable the framework solution will be on a daily basis, to write classes and create those objects.
I thought about tagging the relevant classes with Attributes and then generating a typesafe factory class automatically on build step. Not so sure about naming conflicts, or references that might be needed to compile, as the constructor parameters could be anything.
Also, custom classes could have different constructors, so they should be compatible at each place in default code where they might be constructed already, but still create the custom object. In the custom code then you should be able to use the full custom constructor.
I am currently considering several different cases and possibilities, and can't seem to find a good solution. Maybe I am missing some kind of design pattern, or am not able to look outside of my bubble.
What would be the best design pattern or coding be to implement use cases like this?

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.

Library Input Data via Interface

We are having issues with a pattern, that is emerging in our C# solution.
Initial idea:
We have a set of features (mostly calculations), that are needed in several projects. We imagined our solution to be modular - each feature implemented as a class library which can than be referenced as a .dll in other projects.
First Issue:
What happened was, that libraries had classes, that specified the input data needed for doing the math. As a single library could be used in a number of projects we ended up coding mappings for each project, that ported the projects domain objects to the input data classes. This was tedious, as we were mostly doing a one-to-one conversion - the classes were basically the same.
Idea:
We figured that we would solve our problem with using interfaces instead of classes to specify our input data. That way we could simply label our domain classes with interfaces and we wouldn't have to do the mappings anymore.
Current Issue:
We now have a complete mayhem with interface definitions and the use of these interfaces in calculation methods. E.g.
public interface ILevel2Child
{
}
public interface ILevel1Child<TLevel2Child>
where TLevel2Child : ILevel2Child
{
List<TLevel2Child> Children { get; }
}
public interface IParent<TLevel1Child, TLevel2Child>
where TLevel1Child: ILevel1Child<ILevel2Child>
where TLevel2Child: ILevel2Child
{
List<TLevel1Child> Children { get; }
}
When we end up using the IParent interface in a method or interface, we keep dragging these insanely long signatures along.
Questions:
Was our idea of using interfaces bad to begin with?
If not, is something wrong with the way we specify our interfaces?
If still not, is there any way we can stop this insane signature pattern?
Additional explanation:
We started with
public interface ILevel2Child
{
}
public interface ILevel1Child
{
List<ILevel2Child> Children { get; }
}
public interface IParent
{
List<ILevel1Child> Children { get; }
}
but that prevented us from doing
public class Level2Child : ILevel2Child
{
}
public class Level1Child : ILevel1Child
{
List<Level2Child> Children { get; }
}
public class Parent : IParent
{
List<Level1Child> Children { get; }
}
and that was not acceptable.

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