IRedisTypedClient w/ Runtime Types

Is it possible to generate a typed client using a runtime type?

I.e. Instead of GetClient().As< T>(), passing in a runtimeType like so GetClient().As(Type)?

I notice in your code you often have a Runtime equivalent, but not so with the TypedRedisClient.

I want to be able to call the GetClient().As(runtimeType).DeleteAll() method.

It’s not possible to use the generic APIs with a runtime Type as As<T> returns a typed IRedisTypedClient<T> where its APIs still typed to T. So if you use reflection to create the generic type and get back an object instance of Type IRedisTypedClient<RuntimeType> you wont be able to cast to a runtime type interface that you can call with C# syntax, you’d need to use further reflection to call any of its APIs.

Easiest way in this case is to call redis.DeleteAll<T> generic method through reflection, that way you only need to call one generic method, e.g:

var mi = redis.GetType().GetMethod(nameof(RedisClient.DeleteAll));
var genericMi = mi.MakeGenericMethod(runtimeType);
genericMi.Invoke(redis, TypeConstants.EmptyObjectArray);

Here’s how you would use Reflection to call redis.As<T>().DeleteAll():

var mi = redis.GetType().GetMethod(nameof(RedisClient.As));
var genericMi = mi.MakeGenericMethod(runtimeType);
var typedClient = genericMi.Invoke(redis, TypeConstants.EmptyObjectArray);
var deleteMi = typedClient.GetType().GetMethod(nameof(IRedisTypedClient<Type>.DeleteAll));
deleteMi.Invoke(typedClient, TypeConstants.EmptyObjectArray);

Dynamic Scripting with #Script

If you need to do this a lot, you can also use #Script’s .NET Scripting features which lets you call a .NET methods dynamically using a simpler JS syntax, e.g:

First you’d need to create a script context that gives you access to ProtectedScripts and its configured to allow scripting of all .NET Types:

var context = new ScriptContext {
    ScriptLanguages = { ScriptLisp.Language }, // only if you want to use Lisp
    AllowScriptingOfAllTypes = true,
    ScriptMethods = {
        new ProtectedScripts()
    },
    Args = {
        ["redis"] = redis
    }
}.Init();

Which will then allow you to script your .NET types using the available .NET Scripting APIs, e.g:

var type = runtimeType.FullName;

//Redis.DeleteAll<TRuntimeType>()
context.RenderCode($"redis.call('DeleteAll<{type}>')");

//Redis.As<TRuntimeType>().DeleteAll()
context.RenderCode($"redis.call('As<{type}>').call('DeleteAll')");

Or if you prefer you LISP syntax to JS you can use #Script Lisp instead:

//Redis.DeleteAll<TRuntimeType>()
context.RenderLisp($"(call redis \"DeleteAll<{type}>\")");

//Redis.As<TRuntimeType>().DeleteAll()
context.RenderLisp($"(call (call redis \"As<{type}>\") \"DeleteAll\")");
1 Like

I will test this out now. Thank-you Sir!