This is a project to test out creating a source generator(s) in Roslyn. It's a WIP and more for personal learning/ideas than for production code right now. If I decide to iterate on it further, it may become more stable.
Decorate a public partial class with the [Inject]
attribute on fields to create a constructor which will expose them.
This avoids having to write a constructor in simple situations where it's no more than assigning to a field.
public partial class MyClass {
[Inject] private readonly string _paramter1;
[Inject] private readonly string _paramter2;
}
The constructor should look something like this:
public MyClass(string _parameter1, string _parameter2) {
this._parameter1 = _parameter1;
this._parameter2 = _parameter2;
}
Doesn't support use cases such as inheritance.
This project was meant to auto generate Factories for classes with constructors attributed with a [Factory]
attribute.
The source generator would auto implement a Factory for the class.
I have a unit test that demonstrates this.
[Test]
public void TestExecutionOfSimpleFactory()
{
IInstanceClassFactory factory = new InstanceClassFactory(new InjectedClass());
var testClass = factory.Create("Factory");
Assert.AreEqual("Factory Injected!", testClass.ToString());
}
Where the class that the factory is autogenerated for is here:
public class InjectedClass {
public override string ToString() {
return "Injected!";
}
}
public class InstanceClass {
private readonly string _regularParameter;
private readonly InjectedClass _injectedParameter;
[Factory]
public InstanceClass(string regularParameter, [Inject]InjectedClass injectedClass) {
_regularParameter = regularParameter;
_injectedParameter = injectedClass;
}
public override string ToString() {
return $"{_regularParameter} {_injectedParameter}";
}
}
I want to use the Factory pattern in order to create a class which has some constructor parameters which are dependencies that would be injected by say an DI container, and the others are not available until runtime.
Generates an interface for a class. This is useful for reducing boilerplate code in situations where the interface is only used for mocking.
[Interface]
public partial class MyClass {
[Interface]
public void Method() {
}
[Interface]
public void Method2() {
}
}
public interface IMyClass {
void Method();
void Method2();
}
public partial MyClass : IMyClass {}
Can then DI in the interface, and use it for mocking while unit testing.
services.AddSingleton<IMyClass, MyClass>();
Add the ability to auto generate a factory when auto generating a constructor. With optional parameters provided. Allow combining the interface as well.
Just my personal experience trying to build them.
It's clunky, visual studio requires a reload after each change to debug.
It seems like Visual Studio was keeping a reference to my old source generator after recompile. Had to restart visual studio sometimes for changes to take effect. I had better luck developing in Rider.
Originally, I had limited success.
While I was able to generate a factory, the editing experience in Rider and Visual Studio isn't working to my satisfaction. Full builds and rebuilds of the solution would work fine. However, editing in the project would cause the generated source to be lost and I would start getting errors that the generated factories don't exist.
Reading through this a common problem is having a shared field or property across execution runs: dotnet/roslyn#49249 The intent is that every time execute is run, it should not share state in the class as the two can be run out of sequence and/or by multiple threads.
ISyntaxReceiver = just gets the syntax nodes
ISyntaxContextReceiver = gets the syntax nodes along with the semantic model
There's really only a page or two in the official docs, and certain key markdown pages that are linked to are incomplete or weren't revisited after implementation.