使用统一和泛型时,是否在容器旋转期间注入了封闭类型的实例?如果是,为什么? [英] With unity and generics, are instances of closing types injected during the spinning up of the container and if so why?

查看:49
本文介绍了使用统一和泛型时,是否在容器旋转期间注入了封闭类型的实例?如果是,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎是这种情况。如果将通用标记为封闭类型,则表示要使用类型而不是类型的实例。我在Unity尝试解析下面的ExternalLinkingRepository类中的关闭类型时遇到错误。该错误表明Unity无法协调构造函数,因为存在多个具有相同数量参数(1)的1。我看过构造函数注入器(确实需要一个用于连接字符串的注入器,但这不是问题)关于Unity为什么尝试实例化关闭Type的任何想法?



这是我的容器和代码的注册摘要。我缺少或误解的是什么:

  //自举位置... 
.RegisterType< ICampaignRepository,ExternalLinkingRepository>( )

//具体的存储库-CampaignDataContext是引起问题的原因
公共类ExternalLinkingRepository:RepositoryBase< CampaignDataContext> ;, ICampaignRepository
{
// blah
}

//基类
公共抽象类RepositoryBase< T>其中T:DataContext,IDisposable
{

受保护的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 anyaysis的更多详细代码列表和错误消息
* 容器配置 *

  IUnityContainer容器= new UnityContainer(); 

// ***** NB ****下面的代码引发异常-这是Unity的已知错误
//如果您设置了要中断的异常管理器引发异常(而不是仅由用户处理的异常)将在此处停止。
//但是,在IS框架内处理的异常IS和应用程序的执行可以安全地继续。 Unity的下一版本将解决此问题。
//使用vNext Unity时删除此消息。

容器.RegisterType< IBusinessManager,KnowledgeKubeBusinessManager>()
.RegisterType< IDataManager,KnowledgeKubeDataManager>()
//在这种情况下,将为指定的接口注册特定的具体类型在UserManagerFactory
.RegisterType< IUserManagerFactory,UserManagerFactory>的构造函数中(新的InjectionConstructor(新的ResolvedParameter(typeof(FormsAuthenticatedUserManager)),新的ResolvedParameter(typeof(WindowsAuthenticatedUserManager))))
。 ;()
。 ,外部rnalLinkingRepository>(new InjectionConstructor(ConnectionString))


//使用VirtualMethodInterceptor在KnowledgeKubeDataManager上添加拦截(比TransparentProxyInterceptor快得多)
.AddNewExtension< Interception>()。Configure< ; Interception>()。SetDefaultInterceptorFor< KnowledgeKubeDataManager>(新的VirtualMethodInterceptor())
.Container.AddNewExtension< Interception>()。

ExternalLinkingRepository配置

  ///< summary> 
/// TODO:从Campaign到外部数据链接的一些重构正在进行中。
///< / summary>
公共类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;

试试
{
int productIdx = 0;
foreach(_dataContext.usp_GetKnowledgeAreaIDSByExternalURLID(externalURLID,username)的结果)
{
// blah

错误消息


/ WhiteBox应用程序中的服务器错误。
类型CampaignDataContext具有多个长度为2的构造函数。无法消除歧义。
说明:当前Web请求的执行期间发生未处理的异常。请查看堆栈跟踪以获取有关该错误及其在代码中起源的详细信息。



异常详细信息:System.InvalidOperationException:CampaignDataContext类型具有多个长度为2的构造函数



源错误:



第115行:_container = container;
第116行:

第117行:container.BuildUp(this T);
第118行:

第119行:}



源文件:C:\Development\Acropolis\Development\KnowledgeKube_1 .0.0\Acropolis Suite\WhiteBox\WhiteBox\Web\WhiteBoxBasePage.cs行:117



堆栈跟踪:



[InvalidOperationException:类型CampaignDataContext具有长度大于2的多个构造函数。无法消除歧义。]
Microsoft.Practices.ObjectBuilder2.ConstructorSelectorPolicyBase`1.FindLongestConstructor(> type typeToConstruct)in e:\生成\Unity\UnityTemp\编译\Unity\Unity\Src\ObjectBuilder> \策略\BuildPlan\Creation\ConstructorSelectorPolicyBase.cs:113



解决方案

Unity在设置阶段不会创建对象的实例。但是,当您注册映射时,Unity会尝试标识创建实例时要使用的构造函数。默认情况下,Unity将选择使用最多参数的构造函数(最贪婪的构造函数)。如果有多个构造函数使用最多数量的参数(我不确定,但是从您的描述看来,有两个构造函数带有1个参数?)Unity无法决定要使用哪个构造函数,因此会引发异常。要解决此问题,您可以删除一个构造函数,也可以明确地告诉Unity使用哪个构造函数

  container.RegisterType< ICampaignRepository, ExternalLinkingRepository>(
新的InjectionConstructor( myConnectionString)));

或者如果您的ctor接受了要由Unity解析的参数,则可以通过以下方式指定它们它们的类型

  container.RegisterType< ICampaignRepository,ExternalLinkingRepository>(
新的InjectionConstructor(typeof(IMyTypeThatUnityShouldResolve));


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

解决方案

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));

这篇关于使用统一和泛型时,是否在容器旋转期间注入了封闭类型的实例?如果是,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆