1

I am trying to create multilayer application which consist on DL, BL and GUI modules. DL contains entities, BL contains ViewModels and Services and GUI contains Controllers. My goal is to BL knows about DL, and GUI knows about BL but not DL.

So I have Entity hierarchy like this (in DL):

namespace DL
{
    public abstract class EntityBase
    {
        public int Id { get; set; }
    }

    public class Student : EntityBase
    {
        public string Name { get; set; }
    }
}

And ViewModel hierarchy (in BL module):

namespace BL
{
    public abstract class ViewModelBase
    {
        public int Id { get; set; }
    }

    public class StudentViewModel : ViewModelBase
    {
        public string Name { get; set; }
    }
}

And Services (also in BL):

using DL;

namespace BL
{
    public interface IServiceBase<out TViewModel>
        where TViewModel : ViewModelBase
    {
        TViewModel GetViewModel(int id);
    }

    public abstract class ServiceBase<TEntity, TViewModel> : IServiceBase<TViewModel>
        where TViewModel : ViewModelBase, new()
    {
        public virtual TViewModel GetViewModel(int id)
        {
            return new TViewModel() { Id = id };
        }
    }

    public class StudentsService : ServiceBase<Student, StudentViewModel>
    {
    }
}

And I want to use this in GUI:

using BL;

namespace GUI
{
    class StudentController : ControlerBase<StudentsService, StudentViewModel>
    {
        public StudentController(StudentsService service)
            : base(service)
        {
        }

        public void DoSomething()
        {
            var s = this.service.GetViewModel(123);
        }
    }

    class ControlerBase<TService, TViewModel>
        where TService : IServiceBase<TViewModel>
        where TViewModel : ViewModelBase
    {
        protected readonly TService service;

        public ControlerBase(TService service)
        {
            this.service = service;
        }

        public TViewModel GetViewModel(int id)
        {
            return this.service.GetViewModel(id);
        }
    }
}

It looks good for me. Controllers knows about IService and ViewModels and everything should work, but when I try to compile, I get this error message:

Error 1 The type 'DL.Student' is defined in an assembly that is not referenced. You must add a reference to assembly 'DL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

Ok, I understand that StudentsService derived from generic ServiceBase which is "entity aware". But why compiler bothers that? Moreover, when I'm not calling GetViewModel method in Controller, everything compiles correctly. Why? And when I write in StudentsService completely ridiculous method like this:

public new virtual StudentViewModel GetViewModel(int id)
{
    return base.GetViewModel(id);
}

also everything compiles correctly. Why?

And finally - what should I do, to not writing this bizarre "new virtual" method in all my services?

dwdkls
  • 11
  • 5
  • 6
    How about the obvious, add the missing reference? – Lasse V. Karlsen Nov 10 '14 at 17:32
  • *What should I do...?* Honestly, you should forget about this complicated inheritance. Use an interface for simple properties like `int Id { get; set; }`. Eventually, you will spend more effort to maintain the inheritance hierarchy than you will adding features. On the plus side, you will become a master at hiding methods and virtual method calls, overriding members, internal and sealed classes. And my personal favorite, `InternalsVisibleToAttribute`. Which is to say, you will discover the ninth level of inheritance hell. – Keith Payne Nov 10 '14 at 17:39
  • What are you writing about? I don't want to use strange language constructions and attributes, as you can see this was my motivation to ask this question. Two classes is not complicated inheritance for me and this is something what I need to not losing time for adding features. – dwdkls Nov 10 '14 at 18:16

0 Answers0