简体   繁体   中英

Castle Windsor not creating/exposing Base class

I've got a few Repository classes within a Repository project that uses an Entity Framework DbContext Typed base class.

Base Class

public class RepositoryBase<TC> : IDisposable
    where TC : DbContext, new()
{

    public virtual T Get<T>(...) where T : class
    {
        ...
    }

    // ... additional code
}

Employee Repo Interface

namespace Insight.Repository.Interfaces
{
    public interface IEmployeeRepository
    {
        Result CreateEmployee(Employee employee);
        // ... additional code
    }
}

Employee Repo

namespace Insight.Repository.Repositories
{
    public class EmployeeRepository : RepositoryBase<InsightContext>, IEmployeeRepository
    {
        public Result CreateEmployee(Employee employee)
        {
            return Save(employee);
        }
    }
    // ... additional code
}

I am adding the Repo classes to the Windsor container within an Asp.Mvc website using an installer based on Interfaces within the Repository project. I've looked at the container at this point and I'm getting my three repositories.

public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromAssemblyNamed("Insight.Repository")
           .Where(Component.IsInNamespace("Insight.Repository.Repositories"))
            .WithService.DefaultInterfaces()
            .LifestyleTransient());
    }

I've tried registering the DbContext as follows but I get the same results.

container.Register(Component.For<DbContext>()
            .ImplementedBy<InsightContext>()
            .LifestyleTransient());

Then, within my ApiController, I'm then using Property injection to instantiate the Repo class but I can't get access any of the base class functions.

public class EmployeeController : ApiController
{
    public IEmployeeRepository EmployeeRepo { get; set; }

    [Route("GetEmployee")]
    public void Get()
    {
        var newEmployeeRepo = new EmployeeRepository();
    }
}

EmployeeRepo doesn't have access to the Get() function in the base class but newEmployeeRepo does.

This is my first project using Castle.Windsor and I am clearly missing some sort of registration step but can figure it out.

If someone can point me in the right direction, much appreciated.

Edit: Testing with the Linqpad code supplied by tym32167

void Main()
{
    var container = new WindsorContainer();

    var type = typeof(II);
    container.Register(Classes.FromAssembly(type.Assembly)
       .Where(Component.IsInNamespace(type.Namespace))
        .WithService.AllInterfaces()
        .LifestyleTransient());

    var cls = container.Resolve<II>().Dump();
    cls.GetFirstName().Dump();
    cls.GetLastName().Dump();
}

public interface II
{
    string GetFirstName();
}

public class MyClass : II
{
    public string GetFirstName()
    {
    return "First Name";
    }

    public string GetLastName()
    {
    return "Last Name";
    }
}

The code breaks on this line:

cls.GetLastName().Dump();

Is this the expected behaviour?

Try to replace

.WithService.DefaultInterfaces()

to

.WithService.AllInterfaces()

as sample (just checked with linqpad)

void Main()
{   
    var container = new WindsorContainer();

    var type = typeof(II);
    container.Register(Classes.FromAssembly(type.Assembly)
           .Where(Component.IsInNamespace(type.Namespace))
            .WithService.AllInterfaces()
            .LifestyleTransient());

    container.Resolve<II>().Dump();
}

public interface II
{
}

public class MyCl : II
{
}

To get access to the methods on the base class, you need to have a base interface :)

public interface IBaseRepo<T>
{
     T Get(int id);
     // ...
}

public interface IEmployeeRepo : IBaseRepo<Employee>
{
     Employee GetByFirstName(string name);
     // ...
}

Note how the child interface inherits the base interface. Thus, any type implementing IEmployeeRepo guarantees that it also implements IBaseRepo<Employee> , and when you inject one you get access to the methods on the base interface too.

The fact that you implement the base repo in a base class, that your concrete employee repo inherits, is just an implementation detail that the client code shouldn't have to care about - and now it doesn't!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM