0
votes

Here is my case, I wrote a wcf and it is working with orchard perfectly. I'm going to handle events messages such as warnings and exceptions so I add a ServiceAdapter and ClientServiceLocator to my project :

ServiceAdapter:

public class ServiceAdapter<TService>
 where TService : class, IContract
{
    public TResult Execute<TResult>(Func<TService, TResult> command)
        where TResult : IDtoResponseEnvelop
    {
        try
        {
            var dispatcher = ClientServiceLocator.Instance().CommandDispatcher;
            var result = DispatchCommand(() => dispatcher.ExecuteCommand(command));
            if (result.Response.HasWarning)
            {
                ClientServiceLocator.Instance()
                    .WarningManager
                    .HandleBusinessWarning(result.Response.BusinessWarnings);

            }
            if (result.Response.HasException)
            {
                ClientServiceLocator.Instance()
                    .ExceptionManager
                    .HandleBusinessException(result.Response.BusinessException);
            }
            return result;
        }
        finally
        {
        }
    }

    private static TResult DispatchCommand<TResult>(Func<TResult> dispatcherCommand)
        where TResult : IDtoResponseEnvelop
    {
        var asynchResult = dispatcherCommand.BeginInvoke(null, null);
        while (!asynchResult.IsCompleted)
        {
        }
        return dispatcherCommand.EndInvoke(asynchResult);
    }
}

ClientServiceLocator:

public class ClientServiceLocator
{
    static readonly Object LocatorLock = new object();
    private static ClientServiceLocator InternalInstance;

    private ClientServiceLocator() { }

    public static ClientServiceLocator Instance()
    {
        if (InternalInstance == null)
        {
            lock (LocatorLock)
            {
                // in case of a race scenario ... check again
                if (InternalInstance == null)
                {
                    InternalInstance = new ClientServiceLocator();
                }
            }
        }
        return InternalInstance;
    }

    #region IClientServices Members

    public IBusinessExceptionManager ExceptionManager { get; set; }
    public IBusinessWarningManager WarningManager { get; set; }
    public ICommandDispatcher CommandDispatcher { get; set; }

    #endregion

}

BusinessExceptionManager:

class BusinessExceptionManager
    : IBusinessExceptionManager, IDependency
{
    private Localizer T { get; set; }
    private readonly INotifier _notifier;
    public BusinessExceptionManager(INotifier notifier)
    {
        _notifier = notifier;
        T = NullLocalizer.Instance;
    }
    public void HandleBusinessException(BusinessExceptionDto exceptionDto)
    {
        _notifier.Add(NotifyType.Error, T(exceptionDto.Message));
    }
}

BusinessWarningManager:

class BusinessWarningManager
    : IBusinessWarningManager, IDependency
{
    private Localizer T { get; set; }
    private readonly INotifier _notifier;

    public BusinessWarningManager(INotifier notifier)
    {
        _notifier = notifier;
        T = NullLocalizer.Instance;
    }
    public void HandleBusinessWarning(IEnumerable<BusinessWarning> warnings)
    {
        var message = string.Join(Environment.NewLine, warnings.Select(w => w.Message));
        _notifier.Add(NotifyType.Warning, T(message));
    }
}

Here is the controller:

public class SectorsAdminController : Controller
{
    private dynamic Shape { get; set; }
    private Localizer T { get; set; }
    private readonly INotifier _notifier;
    private readonly ISiteService _siteService;
    private ServiceAdapter<ISectorService> _sectorServiceAdapter;

    public SectorsAdminController(ISiteService siteService, INotifier notifier, IShapeFactory shapeFactory)
    {
        Shape = shapeFactory;
        T = NullLocalizer.Instance;
        _notifier = notifier;
        _siteService = siteService;
        _sectorServiceAdapter = new ServiceAdapter<ISectorService>();
    }

    public ActionResult Index()
    {
        var model = Shape.Sectors(Sectors: _sectorServiceAdapter.Execute(s => s.FindAll()).Sectors);
        return View((object)model);
    }
}

Here is the error:

Oops. Something went wrong ... sorry

An unhandled exception has occurred and the request was terminated. Please refresh the page. If the error persists, go back

Object reference not set to an instance of an object.

System.NullReferenceException: Object reference not set to an instance of an object. Server stack trace: at SAS.Admin.Services.ServiceAdapter1.<>c__DisplayClass31.b__0() at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(Message reqMsg, Boolean bProxyCase) at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(Object NotUsed, MessageData& msgData) at System.Func1.EndInvoke(IAsyncResult result) at SAS.Admin.Services.ServiceAdapter1.Execute[TResult](Func2 command) at SAS.Admin.Controllers.SectorsAdminController.Index() at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.b__3f() at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.b__41() at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.b__41()

1

1 Answers

0
votes

Why would you use a Poor's Man Singleton? I would start by using ISingletonDependency on your IClientServices members, if that is what you need
Get rid of the horrible ServiceLocator, then add IDependency to your ServiceAdapter.

As matter of fact change everything to let Orchard handle instantiation.
I do not see why your ServiceAdapter could not be a simple Service instantiated by your Controller, then each one of your IClientServices created as Providers in your Service.