3

웹 응용 프로그램에서 Microsoft Enterprise Library 5.0 로깅 응용 프로그램 블록을 사용하려고합니다. 주 응용 프로그램에서 로그에 쓸 수 있지만 두 번째 AppDomain에서이 시도 할 때 모든 로그 시도가 예외를 throw합니다 (아래 그림 참조).새 AppDomain의 웹 응용 프로그램에서 "유형 LogWriter를 생성 할 수 없습니다"

콘솔 응용 프로그램에서 정확히 동일한 코드가 작동합니다. 나는 다음과 같은 테스트 코드로 좁혀 (당신의 프로젝트를 일치하도록 어셈블리를 변경하고 이름 상수를 입력해야) : 내가 사용 로깅 구성이 기업에 의해 생성 된 기본 (그냥

public class LogTester 
{ 
    public const string LogWriterAssembly = "LogTest"; 
    public const string LogWriterType = "LogTest.LogWriter"; 

    public static void DoLogTest() 
    { 
     LogWriter localLogger = new LogWriter(); 
     localLogger.Log("In first AppDomain"); 

     AppDomain domain = GetAppDomain(); 

     LogWriter remoteLogger = (LogWriter)domain.CreateInstanceAndUnwrap(LogWriterAssembly, LogWriterType); 
     remoteLogger.Log("In second AppDomain"); 
    } 

    private static AppDomain GetAppDomain() 
    { 
     string baseFolder = AppDomain.CurrentDomain.BaseDirectory; 

     string folder = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath; 

     if (String.IsNullOrEmpty(folder)) 
      folder = baseFolder; 

     AppDomainSetup setup = new AppDomainSetup(); 
     setup.ApplicationName = "TestAppName"; 
     setup.ApplicationBase = baseFolder; 
     setup.PrivateBinPath = folder; 
     setup.ShadowCopyFiles = "true"; 

     return AppDomain.CreateDomain("TestAppName", null, setup); 
    } 
} 

public class LogWriter : MarshalByRefObject 
{ 
    public void Log(string message) 
    { 
     Logger.Write(AppDomain.CurrentDomain.FriendlyName + ": " + message); 
    } 
} 

라이브러리 구성 유틸리티) :

<configSections> 
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" /> 
</configSections> 
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General"> 
    <listeners> 
     <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
      listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
      source="Enterprise Library Logging" formatter="Text Formatter" 
      log="" machineName="." traceOutputOptions="None" /> 
    </listeners> 
    <formatters> 
     <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
      template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}" 
      name="Text Formatter" /> 
    </formatters> 
    <categorySources> 
     <add switchValue="All" name="General"> 
      <listeners> 
       <add name="Event Log Listener" /> 
      </listeners> 
     </add> 
    </categorySources> 
    <specialSources> 
     <allEvents switchValue="All" name="All Events" /> 
     <notProcessed switchValue="All" name="Unprocessed Category" /> 
     <errors switchValue="All" name="Logging Errors &amp; Warnings"> 
      <listeners> 
       <add name="Event Log Listener" /> 
      </listeners> 
     </errors> 
    </specialSources> 
</loggingConfiguration> 

콘솔 응용 프로그램에서 모든 로그 메시지가 잘 작성됩니다. 웹 응용 프로그램에서 두 번째 메시지 쓰기를 시도 할 때, 그러나, 나는 다음과 같은 예외를 얻을 : 내가 필요한 엔터프라이즈 라이브러리 어셈블리에 대한 참조를 가지고

[InvalidOperationException: The type LogWriter cannot be constructed. You must configure the container to supply this value.] 

[ResolutionFailedException: Resolution of the dependency failed, type = "Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter", name = "(none)". 
Exception occurred while: while resolving. 
Exception is: InvalidOperationException - The type LogWriter cannot be constructed. You must configure the container to supply this value. 
----------------------------------------------- 
At the time of the exception, the container was: 

    Resolving Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter,(none) 
] 

[ActivationException: Activation error occured while trying to get instance of type LogWriter, key ""] 
    System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +10582079 
    System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +336 
    MvcApplication1.Controllers.LogWriter.Log(String message) in c:\dev\Sage Data Cloud\Development\MvcApplication1\MvcApplication1\Controllers\DefaultController.cs:65 
    MvcApplication1.Controllers.LogTester.DoLogTest() in c:\dev\Sage Data Cloud\Development\MvcApplication1\MvcApplication1\Controllers\DefaultController.cs:38 
    MvcApplication1.Controllers.DefaultController.Index() in c:\dev\Sage Data Cloud\Development\MvcApplication1\MvcApplication1\Controllers\DefaultController.cs:18 
    lambda_method(Closure , ControllerBase , Object[]) +101 
    System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +59 
    System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +435 
    System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +60 
    System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeSynchronousActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +50 
    System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() +75 
    System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +44 
    System.Web.Mvc.Async.WrappedAsyncResult`1.End() +139 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +102 
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +49 
    System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +126 
    System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +323 
    System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +44 
    System.Web.Mvc.Async.WrappedAsyncResult`1.End() +139 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +102 
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +50 
    System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +68 
    System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +184 
    System.Web.Mvc.Async.WrappedAsyncResult`1.End() +136 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +56 
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +40 
    System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +40 
    System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +47 
    System.Web.Mvc.Async.WrappedAsyncResult`1.End() +151 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40 
    System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44 
    System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +47 
    System.Web.Mvc.Async.WrappedAsyncResult`1.End() +151 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40 
    System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +39 
    System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +39 
    System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +45 
    System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +47 
    System.Web.Mvc.Async.WrappedAsyncResult`1.End() +151 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40 
    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +40 
    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38 
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9629708 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

를, 그래서 로깅, ServiceLocation, 화합과 Unity.Configuration 어셈블리는 로컬로 복사됩니다.

.NET Reflector를 사용하여 엔터프라이즈 라이브러리 코드로 디버깅을 시도했지만 객체 생성이 모두 단계적으로 수행 할 수없는 동적 생성 코드를 사용하여 완료되었습니다. 역방향으로 시도하려고하지 않습니다. 엔지니어링되지 않은 디 컴파일 된 소스에서 엔지니어!).

이전에이 문제를 겪은 사람이 있었는지 궁금한 점이 있습니까? 다른 곳에서는이 같은 문제를 찾을 수 없습니다.

미리 감사드립니다. 피트

+0

월이 [링크] (http://stackoverflow.com/questions/12950547/unity-the-type-logwriter-cannot-be-constructed)하는 데 도움이됩니다. – wonko79

+0

감사합니다.하지만 안타깝게도 var container = new UnityContainer()를 추가하려고 시도했습니다. AddNewExtension ()은 로그에 쓰기 전에 두 번째 AppDomain에서 실행되지만 문제를 해결하지는 않습니다. –

답변

2

새로운 AppDomain에서 엔터프라이즈 라이브러리를 구성 할 수 있도록 새 AppDomain의 구성 파일을 설정해야합니다. 당신은 AppDomainSetup.ConfigurationFile 속성을 사용하여이 작업을 수행 할 수 있습니다

AppDomainSetup setup = new AppDomainSetup(); 
setup.ApplicationName = "TestAppName"; 
setup.ApplicationBase = baseFolder; 
setup.PrivateBinPath = folder; 
setup.ShadowCopyFiles = "true"; 
setup.ConfigurationFile = 
    AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; 
+0

좋습니다. 그 덕분에 많은 감사드립니다. 'ConfigurationFile' 속성을 설정하는 것이 너무 간단하다는 것을 깨닫지 못했습니다. 웹 애플 리케이션과 콘솔 애플 리케이션 사이의 설정 처리에 미묘한 차이가 있어야합니다 ... –