LazyMagic.Client.FactoryGenerator: C# source generator that automatically creates factory classes for dependency injection. Simplifies object creation with mixed constructor parameters (DI-injected and runtime parameters), particularly useful for ViewModels requiring both service dependencies and runtime data.
LazyMagic.Client.FactoryGenerator is a C# source generator that automatically creates factory classes for dependency injection. It simplifies the creation of objects with mixed constructor parameters - some injected via DI and others passed at runtime. This is particularly useful for ViewModels and other classes that require both service dependencies and runtime data.
[Factory]
[Factory]
[FactoryInject]
For each class marked with [Factory]
, the generator creates:
Factory Interface (I{ClassName}Factory
)
Create
method with non-injected parametersFactory Implementation ({ClassName}Factory
)
[FactoryInject]
parametersCreate
method accepts runtime parametersAdditionally, the generator creates per namespace:
{NamespaceNameNoDots}RegisterFactories
)
{NamespaceNameNoDots}Register
[Factory]
public class SessionViewModel : LzViewModel
{
public SessionViewModel(
[FactoryInject] IAuthProcess authProcess,
[FactoryInject] ILogger<SessionViewModel> logger,
IUserViewModel userViewModel,
Session session,
bool? isLoaded = null
) : base(session, isLoaded)
{
// authProcess and logger are injected by DI
// userViewModel, session, and isLoaded are passed at runtime
}
}
public interface ISessionViewModelFactory
{
SessionViewModel Create(
IUserViewModel userViewModel,
Session session,
bool? isLoaded = null);
}
public class SessionViewModelFactory : ISessionViewModelFactory
{
private IAuthProcess authProcess;
private ILogger<SessionViewModel> logger;
public SessionViewModelFactory(
IAuthProcess authProcess,
ILogger<SessionViewModel> logger)
{
this.authProcess = authProcess;
this.logger = logger;
}
public SessionViewModel Create(
IUserViewModel userViewModel,
Session session,
bool? isLoaded = null)
{
return new SessionViewModel(
authProcess,
logger,
userViewModel,
session,
isLoaded);
}
}
namespace MyApp.ViewModels;
public static class MyAppViewModelsRegisterFactories
{
public static void MyAppViewModelsRegister(IServiceCollection services)
{
services.TryAddTransient<ISessionViewModelFactory, SessionViewModelFactory>();
services.TryAddTransient<IUserViewModelFactory, UserViewModelFactory>();
// ... other factories in the namespace
}
}
// In your consuming code
public class SessionService
{
private readonly ISessionViewModelFactory _factory;
public SessionService(ISessionViewModelFactory factory)
{
_factory = factory;
}
public SessionViewModel CreateSessionViewModel(IUserViewModel user, Session session)
{
// Factory handles DI dependencies internally
return _factory.Create(user, session);
}
}
Add to your project file:
<PackageReference Include="LazyMagic.Client.FactoryGenerator"
Version="3.0.0"
PrivateAssets="all"
OutputItemType="Analyzer" />
Note: The OutputItemType="Analyzer"
attribute is required for the generator to work properly.
The generator creates a registration helper per namespace:
// In Program.cs or Startup.cs
using MyApp.ViewModels;
// Register all factories in the namespace
MyAppViewModelsRegisterFactories.MyAppViewModelsRegister(services);
This automatically registers all generated factories as transient services using TryAddTransient
to avoid duplicate registrations.
TryAddTransient
to prevent duplicate service registrations[Factory]
public class UserViewModel : LzItemViewModel<User>
{
public UserViewModel(
[FactoryInject] IAuthService auth,
User user) : base(user)
{
// Auth service injected, user passed at creation
}
}
[Factory]
public class ParentViewModel : LzViewModel
{
public ParentViewModel(
[FactoryInject] IChildViewModelFactory childFactory,
ParentModel model) : base(model)
{
// Can use injected factory to create children
}
}
[Factory]
public class DataService
{
public DataService(
[FactoryInject] IHttpClient http,
[FactoryInject] ILogger logger,
string endpoint)
{
// HTTP client and logger from DI, endpoint at runtime
}
}