With unity and generics, are instances of closi

2019-08-05 13:17发布

It appears this is the case. If I am marking a generic as a closed type, I am stating my intention to use a Type and not an Instance of a Type. I am getting an error as Unity is trying to resolve the closing type in the ExternalLinkingRepository class below. The error states that Unity can not reconcile the constructor as there is more than 1 with the same number of parameters (2). I have looked at constructor injectors (and indeed need one for the connection string, but this is not the issue) Any ideas as to why Unity tries to instantiate the closing Type?

This is a snippet of the registration with my container and code. What am I missing or misunderstanding:

    // Bootstrapping location...
    .RegisterType<ICampaignRepository, ExternalLinkingRepository>()

    // Concrete Repository -- CampaignDataContext is the cause of issue
    public class ExternalLinkingRepository : RepositoryBase<CampaignDataContext>, ICampaignRepository
    { 
      // blah
    }

    //Base class
     public abstract class RepositoryBase<T> where T : DataContext, IDisposable
     {

       protected T _dataContext;

       public RepositoryBase(String connectionString)
       {

        if (_dataContext == null)
        {
            _dataContext = (T)new DataContext(connectionString);
        }

       }

      public void Dispose()
      {
         if (_dataContext != null)
         {
            GC.SuppressFinalize(_dataContext);
            _dataContext.Connection.Close();
         }
      }

}

EDIT More detailed code listing and error messages for anyaysis *Container Config*

      IUnityContainer container = new UnityContainer();

        // *****NB**** The code below throws an exception - this is a know bug with Unity
        // If you have the exception manager set to break on "thrown" exceptions (as opposed to just userhandled exceptions) you will be stopped here. 
        // However, the exception IS handled  within the Unity framework and execution of the application can continue safely. The next release of Unity will fix this. 
        // Remove this message when vNext Unity is used. 

        container.RegisterType<IBusinessManager, KnowledgeKubeBusinessManager>()
        .RegisterType<IDataManager, KnowledgeKubeDataManager>()
            // In this instance, specific concrete types are registered for the interfaces specified in the constructor of the UserManagerFactory
        .RegisterType<IUserManagerFactory, UserManagerFactory>(new InjectionConstructor(new ResolvedParameter(typeof(FormsAuthenticatedUserManager)), new ResolvedParameter(typeof(WindowsAuthenticatedUserManager))))
        .RegisterType<IApplicationConfigurationSettings, ApplicastionConfigurationSettings>()
        .RegisterType<IKnowledgeKubeSessionProvider, KnowledgeKubeManagerSessionProvider>()
        .RegisterType<IQuestionnaireQueryArgs, AnsweredKnowledgeQuestionnaireQueryArgs>()
        .RegisterType<ICampaignBusinessManager, CampaignBusinessManager>()
        .RegisterType<ICampaignRepository, ExternalLinkingRepository>(new InjectionConstructor(ConnectionString))


            // Add Interception on KnowledgeKubeDataManager using the  VirtualMethodInterceptor (Much Faster than the TransparentProxyInterceptor)  
        .AddNewExtension<Interception>().Configure<Interception>().SetDefaultInterceptorFor<KnowledgeKubeDataManager>(new VirtualMethodInterceptor())
        .Container.AddNewExtension<Interception>().Configure<Interception>().SetDefaultInterceptorFor<WindowsAuthenticatedUserManager>(new VirtualMethodInterceptor());

ExternalLinkingRepository config

/// <summary>
/// TODO: Some refactoring going on here from Campaign to external data linking. 
/// </summary>
public class ExternalLinkingRepository : RepositoryBase<CampaignDataContext>, ICampaignRepository
{

    public ExternalLinkingRepository(String connectionString) : base(connectionString) { }


      public void GetKnowledgeAreaIDs(String externalURLID, String username, out Guid userID, out Int32 knowledgeGroupID, out Int32 knowledgeQuestionnaireID)
    {
        knowledgeGroupID = 0;
        knowledgeQuestionnaireID = 0;
        userID = Guid.Empty; 

        try
        {
            int productIdx = 0; 
            foreach (var result in _dataContext.usp_GetKnowledgeAreaIDSByExternalURLID(externalURLID,username))
            {
            // blah

Error Message

Server Error in '/WhiteBox' Application. The type CampaignDataContext has multiple constructors of length 2. Unable to disambiguate. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: The type CampaignDataContext has multiple constructors of length 2. Unable to disambiguate.

Source Error:

Line 115: _container = container; Line 116:
Line 117: container.BuildUp(this as T); Line 118:
Line 119: }

Source File: C:\Development\Acropolis\Development\KnowledgeKube_1.0.0\Acropolis Suite\WhiteBox\WhiteBox\Web\WhiteBoxBasePage.cs Line: 117

Stack Trace:

[InvalidOperationException: The type CampaignDataContext has multiple constructors of >length 2. Unable to disambiguate.] Microsoft.Practices.ObjectBuilder2.ConstructorSelectorPolicyBase`1.FindLongestConstructor(>Type typeToConstruct) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder>\Strategies\BuildPlan\Creation\ConstructorSelectorPolicyBase.cs:113

1条回答
Explosion°爆炸
2楼-- · 2019-08-05 14:17

Unity does not create instances of objects during the setup phase. But when you register a mapping Unity tries to identify the constructor to use when creating an instance. By default Unity will pick the constructor that takes the most parameters (most greedy constructor). If there is more than one constructor that takes the maximum number of parameters (I'm not sure but from your description it sounds like there are two ctors that take 1 parameter?) Unity cannot decide which constructor to use and thus throws an exception. To resolve this issue you can either remove one of the constructors or tell Unity explicitely which constructor to use

container.RegisterType<ICampaignRepository, ExternalLinkingRepository>(
    new InjectionConstructor("myConnectionString"));

or if you have a ctor that takes arguments you want to be resolved by Unity you can specify them by their type

container.RegisterType<ICampaignRepository, ExternalLinkingRepository>(
    new InjectionConstructor(typeof(IMyTypeThatUnityShouldResolve));
查看更多
登录 后发表回答