3

What I want to archieve:

  • Service assembly (project) that holds EntityClasses - pure Data.
  • GUI assembly that extends those Entities for its own pourposes - Runtime information for GUI.

What I tried:

  • Derivation (Gui defines class ExtendedEntity : Service.BaseEntity)

    seems to be the most common and only practicable way to me, but:

    Converting Service.BaseEntity to ExtendedEntity after retrieving Data from the Service is painful. can 'workaround' this by using reflection to generate new ExtendedEntity instances based on base entity instances, but that can't be the 'proper' solution.

  • Partial classes

    is exactly what I'm looking for, except the fact, that it does not work cross-assembly.

I'd greatly appreciate any hints helping me to find a proper & clean solution without reflection cheating =)

Steav
  • 1,478
  • 13
  • 28

3 Answers3

1

This is not a direct answer, but you may want to think a little more about your design. Why does your GUI need intimate knowledge of the mechanics of data storage? Typically we work very hard to make sure that the the UI and the data access are loosely coupled, so we can make changes to either without fear of breaking what already work. The design you are looking to implement can lead to unforeseen problems later.

One common pattern that works well for this type of thing is called the Repository pattern. Essentially the service assembly (repository) would contain all of the knowledge required to push data into and out of a particular data store. The 'shape' of the data is well known, and shared between the GUI and the repository. The service assembly would make the CRUD operations available to the GUI, and the GUI would would hold a reference to the repository, and call methods on it to fetch, create and update the data it needs.

Here are some links to get started on the ideas of loose coupling, the repository pattern, and dependency injection.

Cohesion and coupling

What is dependency injection

What's a good repository pattern tutorial

Community
  • 1
  • 1
Jason
  • 15,915
  • 3
  • 48
  • 72
0

You could have your GUI assembly define extension methods on the entity classes. With appropriate using directives, this would mean the consuming code would not know or care where the methods were actually defined.

A slight annoyance would be the non-existence of extension properties, so even things that are conceptually properties would have to be implemented as methods.

It would look a little like this:

  • In Service assembly

    public class FooDTO
    {
        public string Name { get; set; }
    }
    
  • In GUI assembly

    internal static class Extensions
    {
        // Artificial example!
        public static int GetNameLength(this FooDTO foo)
        {
            return foo.Name.Length;
        }
    }
    
    // Consuming code
    int myFooNameLength =  myFooDTO.GetNameLength();
    
AakashM
  • 62,551
  • 17
  • 151
  • 186
  • Thanks for your reply. Extension methods have come to my mind, aswell. But I am looking for a clean solution, there must be a 'proper' way to do this :-) – Steav Oct 12 '11 at 08:49
0

Is decompilation an option? If yes you can use e.g. PostSharp or Mono Cecil to rewrite the classes in question and add the there the code you want to have them. I am curios why you do not want to use the standard OO approach like derivation. It is definitely not hacking.

The "cleanest" OO solution is to use aggregation and encapsulate the Entity classes inside objects where you can fully control what you can do with the data and how you want to manipulate or query it. You have reached "heaven" when your aggregation class does not need to expose the internal Entity class anymore because your class is powerful enough to support all necessary operations with the right abstractions.

If the classes you want to extend are sealed then you need to think hard why the writers of these classes did not want you to extend them.

Eric Lippert has a nice post about the usages of the sealed keyword.

...

Now, I recognize that developers are highly practical people who just want to get stuff done. Being able to extend any class is convenient, sure. Typical developers say "IS-A-SHMIZ-A, I just want to slap a Confusticator into the Froboznicator class". That developer could write up a hash table to map one to the other, but then you have to worry about when to remove the items, etc, etc, etc -- it's not rocket science, but it is work.

Obviously there is a tradeoff here. The tradeoff is between letting developers save a little time by allowing them to treat any old object as a property bag on the one hand, and developing a well-designed, OOPtacular, fully-featured, robust, secure, predictable, testable framework in a reasonable amount of time -- and I'm going to lean heavily towards the latter. Because you know what? Those same developers are going to complain bitterly if the framework we give them slows them down because it is half-baked, brittle, insecure, and not fully tested!

...

Yours, Alois Kraus

Community
  • 1
  • 1
Alois Kraus
  • 13,229
  • 1
  • 38
  • 64