Steffen
Steffen

Reputation: 53

ServiceStack: resolving services of unknown Type

I have the following Situation: My Service needs to handle different Types of Tasks, each of them getting its own Service-class. There should be a REST-Path /tasks/ (GenericTasksService) to access all of them, and other specific paths like /tasks/specifictask/.

public class Task
{
  public string taskId { get;}
}

public class SpecificTask : Task
{
  public string specificProperty { get; set; }
}

My idea was to register the specific Services with the GenericTasksService like this:

public class GenericTasksService : Service
{
  private static List<ITaskService> taskServices = new List<ITaskService>();

  public static void RegisterTaskService(ITaskService ts) { this.taskServices.Add(ts);}

  public List<Task> Get(GetAllTasks gat) 
  {
     List<Task> tasks = new List<Task>();

     foreach(ITaskService ts in this.taskServices)
        tasks.Add(ts.GetAllTasks());

     return tasks;
  }
}

public class SpecificTaskService : ITaskService
{
   //from ITaskService
   List<Task> GetAllTasks()
   {
     //access Repository and return the List
   }

   //SpecificTask-implementation would follow here
}

I then wanted to register my services in AppHost.Configure by calling

GenericTasksService.RegisterTaskService(new SpecificTaskService());

The problem with this is afaik, that the request context is not set by ServiceStack and so I don't have access to the session. (it is null)

Another option could be to use ResolveService<T> in the GenericTaskService, but I don't know how to do this without knowing the concrete types.

I also tried using AppHostBase.ResolveService<T>(HttpContext httpcx) when registering my TaskServices in AppHostBase.Configure, but at that moment I don't know where to get the RequestContext.

It is my first post at stackoverflow, I hope I did not overlook some conventions. ;) Thanks in advance for your help or suggestions.

Steffen

Upvotes: 2

Views: 321

Answers (1)

Steffen
Steffen

Reputation: 53

I helped myself by registering types instead of instances like this:

public static void RegisterTaskServiceType(System.Type t)
    {
        Type iface = t.GetInterface("itaskservice",true);

        if (iface == null)
            throw new ArgumentException("Type-Argument needs to implement ITaskService.");
        else if (taskServiceTypes.Contains(t))
            throw new InvalidOperationException(string.Format("Type {0} is already registered.",t.FullName));
        else
            taskServiceTypes.Add(t);
    }

In any of my Get-Methods I now resolve the services - if not already done - by using reflection to call the ResolveService<T>-method.

private void ResolveTaskServices()
{
    if (!servicesResolved)
    {
      foreach (Type t in taskServiceTypes)
        {
          //Resolve Service via Reflection and add it to the List of Services
          MethodInfo MethodObj = typeof(TasksService).GetMethod("ResolveService");
          MethodInfo GenericMethodObj = MethodObj.MakeGenericMethod(t);
          taskServices.Add((ITaskService)GenericMethodObj.Invoke(this, new object[] { }));
        }

      servicesResolved = true;
    }
}

I need to implement a few more checks (Type also needs to implement ServiceStack.ServiceInterface.Service) but at least it works.

Upvotes: 1

Related Questions