Code-Sharp / WampSharp-docs

Documentation for the WampSharp project
21 stars 3 forks source link

Injecting scoped services as callee #8

Open kasravi opened 7 years ago

kasravi commented 7 years ago

Hi @darkl , I'm trying to construct my callees as a service. Transient and Singleton services are working as expected, but when I inject scoped services, since there is no HTTP context available, they are created in the default scope and because of that they behave as singleton (we are using a DI pretty similar to .Net Core Di ). I found out that there is also a raw callee which exposes the invocation lifetime where I can create and dispose scopes before and after. Then I should build the wrapper again with another attribute. Is there any better way to achieve scoped invocation of callees?

darkl commented 7 years ago

I'm not sure I understand your problem. What are you trying to achieve?

Elad

kasravi commented 7 years ago

let me write some code (assume that ConfigureServices is called runtime at startup)

    public class RpcService
    {
        public static void ConfigureServices(IServiceCollection serviceCollection)
        {
            serviceCollection.AddTransient(typeof(RpcService));
        }

        public RpcServiceSubA _rpcServiceSubA;
        public UserInfo _userInfo;

        public RpcService(RpcServiceSubA rpcServiceSubA, UserInfo userInfo)
        {
            _rpcServiceSubA = rpcServiceSubA;
            _userInfo = userInfo;
        }

        [WampProcedure("ping")]
        public RpcService Ping()
        {
           return this;
        }
    }

   public class RpcServiceSubA
    {
        public static void ConfigureServices(IServiceCollection serviceCollection)
        {
            serviceCollection.AddTransient(typeof(RpcServiceSubA));
        }

        public UserInfo _userInfo;

        public RpcServiceSubA(UserInfo userInfo)
        {
            _userInfo = userInfo;
        }
    }

   public class UserInfo
    {
        public static void ConfigureServices(IServiceCollection serviceCollection)
        {
            serviceCollection.AddSingleton(typeof(UserInfo));
        }
        public Guid MyKey { get; } = Guid.NewGuid();
    }

We then inject this service like this:

            ....
            using (IWampHost host = new DefaultWampHost(location))
            {
                 IWampHostedRealm realm = host.RealmContainer.GetRealmByName("realm1");

                Task<IAsyncDisposable> registrationTask = realm.Services.RegisterCallee(()=>ServiceManager.GetRequiredService<RpcService>());
                registrationTask.Wait();

                host.Open();

            }

In which the service manager is responsible for providing an instance for every call. Now consider if we register UserInfo as Singleton then we would have same MyKey in diffrent calls of ping: image

if we register it as Transient then we would have diffrent MyKeys since the service manager would new up an instance every time: image

These two are working as expected but if we add UserInfo as Scoped we expect that MyKeys would be same in every RPC call, since they are in different WampInvocationContext. something like this image but the result as I said above is similar to Singleton. I'm trying to make scoped services also work where scopes are created before calls and disposed afterwards.

darkl commented 7 years ago

Cool. Does your DI support custom scopes?

kasravi commented 7 years ago

I'm not sure about the definition of custom scope but if you mean something like here then no. we just have the Transient, Singleton and something like Request. (our DI is completely similar to .Net Core DI)

darkl commented 7 years ago

That's a bummer, since with Ninject you could simply write:

kernel.Bind<UserInfo>().ToSelf().InScope(x => WampInvocationContext.Current);
kasravi commented 7 years ago

aah, well one way for me is to see what is happening in Ninject's custom scopes and if I can add this kind of scopes to our framework. I will continue this thread if there is no easy way towards custom scopes. thanks!