I'm working on a Blazor Wasm Hosted project that uses dynamic razor components for rendering the UI. The components are created using the IDynamicComponent
interface. At server-side, the dlls are loaded and stored into IEnumerable<Type>
. From this IEnumerable<Type>
I can get individual component by name and casted to IDynamicComponent
. The issue is that I can't be able to send the component in this format to the client via SignalR.
IDynamicComponent
Interface
public interface IDynamicComponent
{
IDictionary<Type,Type> InjectableDependencies { get; }
IDictionary<string,string> Parameters { get; }
string Name { get; }
Type Component { get;}
}
Example of component
The component is created separately in a Razor Class Library project which consist of "MyComponent.cs" and "RazorComponent1.razor". The dll is then loaded to get MyComponent
.
public class MyComponent : IDynamicComponent
{
public IDictionary<Type, Type> InjectableDependencies => new Dictionary<Type, Type>();
public IDictionary<string, string> Parameters => new Dictionary<string, string>();
public string Name => "ComponentName";
public Type Component => typeof(RazorComponent1); // RazorComponent1.razor
}
A) Server-side: Load the Component Dlls
public IEnumerable<Type> Components { get; private set; }
// Loads the dlls and stores the components in 'IEnumerable<Type>'
public void LoadComponents(string path)
{
var components = new List<Type>();
var assemblies = LoadAssemblies(path);
foreach (var asm in assemblies)
{
var types = GetTypesWithInterface(asm);
foreach (var typ in types) components.Add(typ);
}
Components = components;
}
B) Server-side: Function to get individual Component by name
// Gets the component by name
public IDynamicComponent GetComponentByName(string name)
{
return Components.Select(x => (IDynamicComponent)Activator.CreateInstance(x))
.SingleOrDefault(x => x.Name == name);
}
C) Server-side: Send to Client via SignalR
// Sends a component to client via SignalR when requested.
public async Task GetPlugin()
{
IDynamicComponent component = ComponentService.GetComponentByName("Counter");
string comp = JsonConvert.SerializeObject(component);
await myHub.Clients.All.SendAsync("Plugin", comp);
}
D) Client-side: Receive component and cast to IDynamicComponent
hubConnection.On<string>("Plugin", (comp) =>
{
IDynamicComponent component = JsonConvert.DeserializeObject<IDynamicComponent>(comp);
UpdateBlazorUIEvent?.Invoke();
});
Error at part D) shown in browser console
Could not create an instance of type Blazor.Shared.Plugin.IDynamicComponent. Type is an interface or abstract class and cannot be instantiated. Path 'InjectableDependencies', line 1, position 26.