Skip to content

Instantly share code, notes, and snippets.

@oising
Created December 5, 2024 17:18
Show Gist options
  • Save oising/0a650ba22e1dd69d80cdfc182f377722 to your computer and use it in GitHub Desktop.
Save oising/0a650ba22e1dd69d80cdfc182f377722 to your computer and use it in GitHub Desktop.
Remove need to pass Actor type string when instantiating actors with dotnet sdk and actor source generator
// requires that you're already using the actor source generator package
public static class TypedActorProxyFactory
{
private static readonly FrozenDictionary<Type, string> Map;
static TypedActorProxyFactory()
{
Map = (from Assembly e in AppDomain.CurrentDomain.GetAssemblies()
where e.FullName is not null && !e.FullName.StartsWith("System.") // skip dynamic and coreclr assemblies
from t in e.GetTypes()
where t.IsClass &&
typeof(IActor).IsAssignableFrom(t) &&
!typeof(Actor).IsAssignableFrom(t) && // exclude actor impl
t.Name.EndsWith("Client") // isolate typed client
select new
{
Client = t,
Metadata = new
{
ActorTypeString = t.Name[..t.Name.LastIndexOf("Client", StringComparison.Ordinal)],
Interfaces = t.GetInterfaces().Where(i => typeof(IActor).IsAssignableFrom(i)) // not used (yet?)
}
})
.ToDictionary(x => x.Client, x => x.Metadata.ActorTypeString)
.ToFrozenDictionary();
}
public static TActorClient Create<TActorClient>(ActorId actorId) where TActorClient : class, IActor
{
if (typeof(Actor).IsAssignableFrom(typeof(TActorClient)))
{
throw new InvalidOperationException("Cannot create an actor client for an actor implementation. " +
"Please pass the source generated client as TActorClient.");
}
var proxy = ActorProxy.Create(actorId, Map[typeof(TActorClient)]);
return (TActorClient?)Activator.CreateInstance(typeof(TActorClient), proxy) ?? throw new InvalidOperationException();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment