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?

0

There are 0 answers