Castle Windsor with Multiple Constructors

筅森魡賤 提交于 2019-12-01 16:45:00

问题


I am currently undertaking a conversion, from to the use of Ninject, to the current release of Castle Windsor for a simple C# .NET application.

For the most part, the conversion has gone well and the implementation of the containers has executed flawlessly. I am however having a small issue with my repository objects.

I have a user repository object that is coded in the following fashion:

public class UserRepository : IUserRepository {
    public UserRepository(IObjectContext objectContext)  {
        // Check that the supplied arguments are valid.
        Validate.Arguments.IsNotNull(objectContext, "objectContext");

        // Initialize the local fields.
        ObjectContext = objectContext;
    }

    public UserRepository(IObjectContextFactory factory) 
        : this(factory.CreateObjectContext()) { 
    }

    // -----------------------------------------------
    // Insert methods and properties...
    // -----------------------------------------------
}

To correspond to this code, I have setup the following entries in my application's configuration file:

<castle>
    <components>
        <component id="objectContextFactory" lifestyle="custom"
                   customLifestyleType="Common.Infrastructure.PerWebRequestLifestyleManager, Common.Castle"
                   service="Project.DAL.Context.IObjectContextFactory, Project.DAL.LINQ"
                   type="project.DAL.Context.ObjectContextFactory, Project.DAL.LINQ">
        </component>
        <component id="userRepository" lifestyle="custom"
                   customLifestyleType="Common.Infrastructure.PerWebRequestLifestyleManager, Common.Castle"
                   service="Project.BL.Repository.IUserRepository, Project.BL"
                   type="Project.BL.Repository.UserRepository, Project.BL.LINQ">
            <parameters>
              <factory>${objectContextFactory}</factory>
            </parameters>
        </component>
    </components>
</castle>

To me, everything looks like it should. When I attempt to resolve an instance of the IObjectContextFactory service, I retrieve an ObjectContextFactory object. My problem comes in when I try and resolve an instance of the IUserRepository service. I am treated to the following delightful exception:

Can't create component 'userRepository' as it has dependencies to be satisfied. userRepository is waiting for the following dependencies:

Services:

- SandCastle.DAL.Context.IObjectContext which was not registered.

I've tried everything I can think of on this. So, unto you stackoverflow readers, I say: got any ideas?


回答1:


This might be regarded as a bug (and indeed for cases like this it's fixable) but it's kindof a by-design feature.

Windsor tries to match the greediest constructor (one with the most parameters) it can satisfy.

However in your case, there are two constructors that have the greatest number of parameters (of one), so Windsor just picks the first, where what the "first" means is undefined.

indeed if you switch the order of your constructors in your source code your code will start working, although it's a hack, relying on undocumented behavior and don't do it.

Let's go back to where we started shall we?

I said Windsor is confused because there's no single greediest constructor it can satisfy.

Quick and well-defined fix would be to add a fake parameter to one of th constructors so that they have different numbers of parameters:

public class UserRepository : IUserRepository {
    public UserRepository(IObjectContext objectContext, object fakeIgnoreMe)  {
        // Check that the supplied arguments are valid.
        Validate.Arguments.IsNotNull(objectContext, "objectContext");
        // ignoring fake additional argument
        // Initialize the local fields.
        ObjectContext = objectContext;
    }

    public UserRepository(IObjectContextFactory factory) 
        : this(factory.CreateObjectContext()) { 
    }

    // -----------------------------------------------
    // Insert methods and properties...
    // -----------------------------------------------
}

Please report this issue to Castle users list or straight to issue tracker so that it will get fixed.




回答2:


As of Windsor 3.2.x

If the attribute Castle.Core.DoNotSelectAttribute is applied to a constructor, it will not be selected, notwithstanding any other criteria.

public class UserRepository : IUserRepository
{
    [DoNotSelect] // This constructor will be ignored by Windsor
    public UserRepository(IObjectContext objectContext)
    {
        // ...
    }

    public UserRepository(IObjectContextFactory factory)
        : this(factory.CreateObjectContext()) {}
}

Reference: https://github.com/castleproject/Windsor/blob/86696989a7698c45b992eb6e7a67b765b48108b0/docs/how-constructor-is-selected.md



来源:https://stackoverflow.com/questions/1746387/castle-windsor-with-multiple-constructors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!